From 12e05e026aa33b9c2ad6904072588f44e0ede35f Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Tue, 17 Sep 2024 15:44:06 +0530 Subject: [PATCH 01/41] Merge branch 'ESS-ENN-ESS-ENN' into main --- package-lock.json | 64 +++++++++---------- package.json | 4 +- rules/c/security/libxml2-audit-parser-c.yml | 25 ++++++++ rules/c/security/sizeof-this-c.yml | 13 ++++ .../cpp/security/libxml2-audit-parser-cpp.yml | 25 ++++++++ .../csharp/security/httponly-false-csharp.yml | 25 ++++++++ .../security/plaintext-http-link-html.yml | 14 ++++ .../java/security/cbc-padding-oracle-java.yml | 17 +++++ rules/java/security/cbc-padding-oracle.yml | 16 ----- .../cookie-secure-flag-false-java.yml | 14 ++++ .../java/security/des-is-deprecated-java.yml | 16 +++++ .../security/desede-is-deprecated-java.yml | 16 +++++ ...ry-external-general-entities-true-java.yml | 16 +++++ rules/java/security/ecb-cipher-java.yml | 17 +++++ rules/java/security/no-null-cipher-java.yml | 17 +++++ rules/java/security/rsa-no-padding-java.yml | 14 ++++ ...stem-setproperty-hardcoded-secret-java.yml | 22 +++++++ .../java/security/unencrypted-socket-java.yml | 16 +++++ rules/java/security/use-of-aes-ecb-java.yml | 22 +++++++ rules/java/security/use-of-blowfish-java.yml | 17 +++++ .../security/use-of-md5-digest-utils-java.yml | 13 ++++ rules/java/security/use-of-md5-java.yml | 20 ++++++ rules/java/security/use-of-rc2-java.yml | 13 ++++ rules/java/security/use-of-rc4-java.yml | 16 +++++ rules/java/security/use-of-sha1-java.yml | 20 ++++++ .../security/use-of-weak-rsa-key-java.yml | 16 +++++ rules/java/security/weak-ssl-context-java.yml | 22 +++++++ .../security/des-is-deprecated-kotlin.yml | 16 +++++ .../security/desede-is-deprecated-kotlin.yml | 16 +++++ .../kotlin/security/rsa-no-padding-kotlin.yml | 14 ++++ ...em-setproperty-hardcoded-secret-kotlin.yml | 22 +++++++ .../security/use-of-weak-rsa-key-kotlin.yml | 18 ++++++ .../security/reqwest-accept-invalid-rust.yml | 17 +++++ .../scala/security/rsa-padding-set-scala.yml | 18 ++++++ .../xmlinputfactory-dtd-enabled-scala.yml | 22 +++++++ .../security/insecure-biometrics-swift.yml | 19 ++++++ .../cbc-padding-oracle-java-snapshot.yml | 15 +++++ ...cookie-secure-flag-false-java-snapshot.yml | 9 +++ .../des-is-deprecated-java-snapshot.yml | 9 +++ .../des-is-deprecated-kotlin-snapshot.yml | 9 +++ .../desede-is-deprecated-java-snapshot.yml | 10 +++ .../desede-is-deprecated-kotlin-snapshot.yml | 10 +++ ...al-general-entities-true-java-snapshot.yml | 10 +++ .../ecb-cipher-java-snapshot.yml | 9 +++ .../httponly-false-csharp-snapshot.yml | 16 +++++ .../insecure-biometrics-swift-snapshot.yml | 9 +++ .../libxml2-audit-parser-c-snapshot.yml | 12 ++++ .../libxml2-audit-parser-cpp-snapshot.yml | 12 ++++ .../no-null-cipher-java-snapshot.yml | 18 ++++++ .../plaintext-http-link-html-snapshot.yml | 15 +++++ .../reqwest-accept-invalid-rust-snapshot.yml | 30 +++++++++ .../rsa-no-padding-java-snapshot.yml | 18 ++++++ .../rsa-no-padding-kotlin-snapshot.yml | 10 +++ .../rsa-padding-set-scala-snapshot.yml | 15 +++++ .../__snapshots__/sizeof-this-c-snapshot.yml | 9 +++ ...roperty-hardcoded-secret-java-snapshot.yml | 10 +++ ...perty-hardcoded-secret-kotlin-snapshot.yml | 10 +++ .../unencrypted-socket-java-snapshot.yml | 58 +++++++++++++++++ .../use-of-aes-ecb-java-snapshot.yml | 10 +++ .../use-of-blowfish-java-snapshot.yml | 16 +++++ .../use-of-md5-digest-utils-java-snapshot.yml | 9 +++ .../use-of-md5-java-snapshot.yml | 9 +++ .../use-of-rc2-java-snapshot.yml | 10 +++ .../use-of-rc4-java-snapshot.yml | 16 +++++ .../use-of-sha1-java-snapshot.yml | 10 +++ .../use-of-weak-rsa-key-java-snapshot.yml | 34 ++++++++++ .../use-of-weak-rsa-key-kotlin-snapshot.yml | 10 +++ .../weak-ssl-context-java-snapshot.yml | 37 +++++++++++ ...nputfactory-dtd-enabled-scala-snapshot.yml | 19 ++++++ tests/c/libxml2-audit-parser-c-test.yml | 8 +++ tests/c/sizeof-this-c-test.yml | 7 ++ tests/cpp/libxml2-audit-parser-cpp-test.yml | 8 +++ tests/csharp/httponly-false-csharp-test.yml | 11 ++++ tests/html/plaintext-http-link-html-test.yml | 15 +++++ tests/java/cbc-padding-oracle-java-test.yml | 7 ++ tests/java/cbc-padding-oracle-test.yml | 11 ---- .../cookie-secure-flag-false-java-test.yml | 10 +++ tests/java/des-is-deprecated-java-test.yml | 7 ++ tests/java/desede-is-deprecated-java-test.yml | 8 +++ ...ternal-general-entities-true-java-test.yml | 9 +++ tests/java/ecb-cipher-java-test.yml | 7 ++ tests/java/no-null-cipher-java-test.yml | 8 +++ tests/java/rsa-no-padding-java-test.yml | 8 +++ ...setproperty-hardcoded-secret-java-test.yml | 9 +++ tests/java/unencrypted-socket-java-test.yml | 23 +++++++ tests/java/use-of-aes-ecb-java-test.yml | 8 +++ tests/java/use-of-blowfish-java-test.yml | 9 +++ .../use-of-md5-digest-utils-java-test.yml | 9 +++ tests/java/use-of-md5-java-test.yml | 7 ++ tests/java/use-of-rc2-java-test.yml | 8 +++ tests/java/use-of-rc4-java-test.yml | 9 +++ tests/java/use-of-sha1-java-test.yml | 10 +++ tests/java/use-of-weak-rsa-key-java-test.yml | 18 ++++++ tests/java/weak-ssl-context-java-test.yml | 19 ++++++ .../kotlin/des-is-deprecated-kotlin-test.yml | 7 ++ .../desede-is-deprecated-kotlin-test.yml | 8 +++ tests/kotlin/rsa-no-padding-kotlin.yml | 8 +++ ...tproperty-hardcoded-secret-kotlin-test.yml | 9 +++ .../use-of-weak-rsa-key-kotlin-test.yml | 9 +++ .../rust/reqwest-accept-invalid-rust-test.yml | 13 ++++ tests/scala/rsa-padding-set-scala-test.yml | 9 +++ ...xmlinputfactory-dtd-enabled-scala-test.yml | 11 ++++ .../swift/insecure-biometrics-swift-test.yml | 7 ++ 103 files changed, 1448 insertions(+), 61 deletions(-) create mode 100644 rules/c/security/libxml2-audit-parser-c.yml create mode 100644 rules/c/security/sizeof-this-c.yml create mode 100644 rules/cpp/security/libxml2-audit-parser-cpp.yml create mode 100644 rules/csharp/security/httponly-false-csharp.yml create mode 100644 rules/html/security/plaintext-http-link-html.yml create mode 100644 rules/java/security/cbc-padding-oracle-java.yml delete mode 100644 rules/java/security/cbc-padding-oracle.yml create mode 100644 rules/java/security/cookie-secure-flag-false-java.yml create mode 100644 rules/java/security/des-is-deprecated-java.yml create mode 100644 rules/java/security/desede-is-deprecated-java.yml create mode 100644 rules/java/security/documentbuilderfactory-external-general-entities-true-java.yml create mode 100644 rules/java/security/ecb-cipher-java.yml create mode 100644 rules/java/security/no-null-cipher-java.yml create mode 100644 rules/java/security/rsa-no-padding-java.yml create mode 100644 rules/java/security/system-setproperty-hardcoded-secret-java.yml create mode 100644 rules/java/security/unencrypted-socket-java.yml create mode 100644 rules/java/security/use-of-aes-ecb-java.yml create mode 100644 rules/java/security/use-of-blowfish-java.yml create mode 100644 rules/java/security/use-of-md5-digest-utils-java.yml create mode 100644 rules/java/security/use-of-md5-java.yml create mode 100644 rules/java/security/use-of-rc2-java.yml create mode 100644 rules/java/security/use-of-rc4-java.yml create mode 100644 rules/java/security/use-of-sha1-java.yml create mode 100644 rules/java/security/use-of-weak-rsa-key-java.yml create mode 100644 rules/java/security/weak-ssl-context-java.yml create mode 100644 rules/kotlin/security/des-is-deprecated-kotlin.yml create mode 100644 rules/kotlin/security/desede-is-deprecated-kotlin.yml create mode 100644 rules/kotlin/security/rsa-no-padding-kotlin.yml create mode 100644 rules/kotlin/security/system-setproperty-hardcoded-secret-kotlin.yml create mode 100644 rules/kotlin/security/use-of-weak-rsa-key-kotlin.yml create mode 100644 rules/rust/security/reqwest-accept-invalid-rust.yml create mode 100644 rules/scala/security/rsa-padding-set-scala.yml create mode 100644 rules/scala/security/xmlinputfactory-dtd-enabled-scala.yml create mode 100644 rules/swift/security/insecure-biometrics-swift.yml create mode 100644 tests/__snapshots__/cbc-padding-oracle-java-snapshot.yml create mode 100644 tests/__snapshots__/cookie-secure-flag-false-java-snapshot.yml create mode 100644 tests/__snapshots__/des-is-deprecated-java-snapshot.yml create mode 100644 tests/__snapshots__/des-is-deprecated-kotlin-snapshot.yml create mode 100644 tests/__snapshots__/desede-is-deprecated-java-snapshot.yml create mode 100644 tests/__snapshots__/desede-is-deprecated-kotlin-snapshot.yml create mode 100644 tests/__snapshots__/documentbuilderfactory-external-general-entities-true-java-snapshot.yml create mode 100644 tests/__snapshots__/ecb-cipher-java-snapshot.yml create mode 100644 tests/__snapshots__/httponly-false-csharp-snapshot.yml create mode 100644 tests/__snapshots__/insecure-biometrics-swift-snapshot.yml create mode 100644 tests/__snapshots__/libxml2-audit-parser-c-snapshot.yml create mode 100644 tests/__snapshots__/libxml2-audit-parser-cpp-snapshot.yml create mode 100644 tests/__snapshots__/no-null-cipher-java-snapshot.yml create mode 100644 tests/__snapshots__/plaintext-http-link-html-snapshot.yml create mode 100644 tests/__snapshots__/reqwest-accept-invalid-rust-snapshot.yml create mode 100644 tests/__snapshots__/rsa-no-padding-java-snapshot.yml create mode 100644 tests/__snapshots__/rsa-no-padding-kotlin-snapshot.yml create mode 100644 tests/__snapshots__/rsa-padding-set-scala-snapshot.yml create mode 100644 tests/__snapshots__/sizeof-this-c-snapshot.yml create mode 100644 tests/__snapshots__/system-setproperty-hardcoded-secret-java-snapshot.yml create mode 100644 tests/__snapshots__/system-setproperty-hardcoded-secret-kotlin-snapshot.yml create mode 100644 tests/__snapshots__/unencrypted-socket-java-snapshot.yml create mode 100644 tests/__snapshots__/use-of-aes-ecb-java-snapshot.yml create mode 100644 tests/__snapshots__/use-of-blowfish-java-snapshot.yml create mode 100644 tests/__snapshots__/use-of-md5-digest-utils-java-snapshot.yml create mode 100644 tests/__snapshots__/use-of-md5-java-snapshot.yml create mode 100644 tests/__snapshots__/use-of-rc2-java-snapshot.yml create mode 100644 tests/__snapshots__/use-of-rc4-java-snapshot.yml create mode 100644 tests/__snapshots__/use-of-sha1-java-snapshot.yml create mode 100644 tests/__snapshots__/use-of-weak-rsa-key-java-snapshot.yml create mode 100644 tests/__snapshots__/use-of-weak-rsa-key-kotlin-snapshot.yml create mode 100644 tests/__snapshots__/weak-ssl-context-java-snapshot.yml create mode 100644 tests/__snapshots__/xmlinputfactory-dtd-enabled-scala-snapshot.yml create mode 100644 tests/c/libxml2-audit-parser-c-test.yml create mode 100644 tests/c/sizeof-this-c-test.yml create mode 100644 tests/cpp/libxml2-audit-parser-cpp-test.yml create mode 100644 tests/csharp/httponly-false-csharp-test.yml create mode 100644 tests/html/plaintext-http-link-html-test.yml create mode 100644 tests/java/cbc-padding-oracle-java-test.yml delete mode 100644 tests/java/cbc-padding-oracle-test.yml create mode 100644 tests/java/cookie-secure-flag-false-java-test.yml create mode 100644 tests/java/des-is-deprecated-java-test.yml create mode 100644 tests/java/desede-is-deprecated-java-test.yml create mode 100644 tests/java/documentbuilderfactory-external-general-entities-true-java-test.yml create mode 100644 tests/java/ecb-cipher-java-test.yml create mode 100644 tests/java/no-null-cipher-java-test.yml create mode 100644 tests/java/rsa-no-padding-java-test.yml create mode 100644 tests/java/system-setproperty-hardcoded-secret-java-test.yml create mode 100644 tests/java/unencrypted-socket-java-test.yml create mode 100644 tests/java/use-of-aes-ecb-java-test.yml create mode 100644 tests/java/use-of-blowfish-java-test.yml create mode 100644 tests/java/use-of-md5-digest-utils-java-test.yml create mode 100644 tests/java/use-of-md5-java-test.yml create mode 100644 tests/java/use-of-rc2-java-test.yml create mode 100644 tests/java/use-of-rc4-java-test.yml create mode 100644 tests/java/use-of-sha1-java-test.yml create mode 100644 tests/java/use-of-weak-rsa-key-java-test.yml create mode 100644 tests/java/weak-ssl-context-java-test.yml create mode 100644 tests/kotlin/des-is-deprecated-kotlin-test.yml create mode 100644 tests/kotlin/desede-is-deprecated-kotlin-test.yml create mode 100644 tests/kotlin/rsa-no-padding-kotlin.yml create mode 100644 tests/kotlin/system-setproperty-hardcoded-secret-kotlin-test.yml create mode 100644 tests/kotlin/use-of-weak-rsa-key-kotlin-test.yml create mode 100644 tests/rust/reqwest-accept-invalid-rust-test.yml create mode 100644 tests/scala/rsa-padding-set-scala-test.yml create mode 100644 tests/scala/xmlinputfactory-dtd-enabled-scala-test.yml create mode 100644 tests/swift/insecure-biometrics-swift-test.yml diff --git a/package-lock.json b/package-lock.json index e27fa3a8..3fc6cfdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,13 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { - "@ast-grep/cli": "^0.20.2" + "@ast-grep/cli": "^0.26.0" } }, "node_modules/@ast-grep/cli": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@ast-grep/cli/-/cli-0.20.2.tgz", - "integrity": "sha512-PhDdxSiyLTyZZ4udvKrthGPNDoNp1Euqfvql66eh5m4F+/PYjMwTPz/5lwYvHZpIr2MozZ1Jqm9W2btjwE3fnw==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/@ast-grep/cli/-/cli-0.26.3.tgz", + "integrity": "sha512-5HiNeR4uuwVd01VqGW8J6v76PpmcEHG+1YzObXBGfr8XTV7zyYtx4KEVv7hi/PhTpeYylqsir0aRoPk1jlTjsA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -29,19 +29,19 @@ "node": ">= 12.0.0" }, "optionalDependencies": { - "@ast-grep/cli-darwin-arm64": "0.20.2", - "@ast-grep/cli-darwin-x64": "0.20.2", - "@ast-grep/cli-linux-arm64-gnu": "0.20.2", - "@ast-grep/cli-linux-x64-gnu": "0.20.2", - "@ast-grep/cli-win32-arm64-msvc": "0.20.2", - "@ast-grep/cli-win32-ia32-msvc": "0.20.2", - "@ast-grep/cli-win32-x64-msvc": "0.20.2" + "@ast-grep/cli-darwin-arm64": "0.26.3", + "@ast-grep/cli-darwin-x64": "0.26.3", + "@ast-grep/cli-linux-arm64-gnu": "0.26.3", + "@ast-grep/cli-linux-x64-gnu": "0.26.3", + "@ast-grep/cli-win32-arm64-msvc": "0.26.3", + "@ast-grep/cli-win32-ia32-msvc": "0.26.3", + "@ast-grep/cli-win32-x64-msvc": "0.26.3" } }, "node_modules/@ast-grep/cli-darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@ast-grep/cli-darwin-arm64/-/cli-darwin-arm64-0.20.2.tgz", - "integrity": "sha512-gBjMyd42ajDzzRjVKMg81slI7Nkp+0BWIBcCa3ZD0jqf9yQ5I+lAHKkDuC31kzcXw6XF2SSlIICRn9mEQhr21w==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-darwin-arm64/-/cli-darwin-arm64-0.26.3.tgz", + "integrity": "sha512-RM9g0sbcMfiNrxmHfMkfzkSNQFQrHQjcHYtHFnHFVj5uTJP6gXjQnUVLEJiB/glPDVRHCiMkSt/CY7WNaPcyew==", "cpu": [ "arm64" ], @@ -55,9 +55,9 @@ } }, "node_modules/@ast-grep/cli-darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@ast-grep/cli-darwin-x64/-/cli-darwin-x64-0.20.2.tgz", - "integrity": "sha512-sllsHYgRceB4dt1ncnIjVCO449/fewNt8eqcygmomOkdQzRR81UIcuR/ruIZdVti1rqNhMNKhE5mf+GUITA1GQ==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-darwin-x64/-/cli-darwin-x64-0.26.3.tgz", + "integrity": "sha512-6ayT5opqNr57vJYyAUYgrF5oRLlCzZ/c8t+bcIdkxGcugnqbOcKmleoaC4v3R/wWTAjil6DR12NCOnoouR99lw==", "cpu": [ "x64" ], @@ -71,9 +71,9 @@ } }, "node_modules/@ast-grep/cli-linux-arm64-gnu": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@ast-grep/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-0.20.2.tgz", - "integrity": "sha512-7gm6ei4oiMA1u8BXbKBX6+daQhlmS1DqhliQdFmIrOJLv3oB5fBMIk3gn+0UMDthDHZIeoJn+ig2BOcfqaoyGg==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-0.26.3.tgz", + "integrity": "sha512-dTDbJqUgzkWxXjTJjeUJSAVgB7uL3M/34a8OoTB+VEZxGg2N/RSBSRinrTG4lIjeFk4OMJuM+2AppAjhaMTD+g==", "cpu": [ "arm64" ], @@ -87,9 +87,9 @@ } }, "node_modules/@ast-grep/cli-linux-x64-gnu": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@ast-grep/cli-linux-x64-gnu/-/cli-linux-x64-gnu-0.20.2.tgz", - "integrity": "sha512-mAd1msrGRmsk7omlqPhqEUiBjs4Q/C+xUBAIw2yX18g5Aq07zPc2KWwA2wGwaa9dBYr0gnZd1o9DiSrDeUJpEA==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-linux-x64-gnu/-/cli-linux-x64-gnu-0.26.3.tgz", + "integrity": "sha512-V2s+xFXmLKRidoVY6GLZCbofSgPGNXJgJehzhV8JdCVJw7yasl+03x6YSusan8vDon+LWtxjrKe6KDgWOMPEkw==", "cpu": [ "x64" ], @@ -103,9 +103,9 @@ } }, "node_modules/@ast-grep/cli-win32-arm64-msvc": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@ast-grep/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-0.20.2.tgz", - "integrity": "sha512-VJEum6wD+jfkWR7mxT9DlXovY0SZMIlgvTx/3dmQAiEbk0NiKwit6kofKW3+smHQlVxdtznDSLfKcfll+WhEmA==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-0.26.3.tgz", + "integrity": "sha512-7FUCYHf6NonovqPSJ5dCEcI1cW8ipeX+jz+MTSLaI4lak2/FBkkYIjtRuRvpviUnjKHx0Ah7AmO6G1OGiKhzzg==", "cpu": [ "arm64" ], @@ -119,9 +119,9 @@ } }, "node_modules/@ast-grep/cli-win32-ia32-msvc": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@ast-grep/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-0.20.2.tgz", - "integrity": "sha512-d2hlxWVENNsRNN9XTiuxv6UhjbfMj8F+4D6D/Uyfyah35E3UejyNxf9K3NymoCOSdpp+YX2iiP9pW1aMQjurgw==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-0.26.3.tgz", + "integrity": "sha512-phMsiig9GzQBJQJ75wOh98ug8uptbonBkLAAlkpJ2RF0QVrCWG+MqgYBHpSpJiaM/uRJ7IlFclLFc8kpON5cVQ==", "cpu": [ "ia32" ], @@ -135,9 +135,9 @@ } }, "node_modules/@ast-grep/cli-win32-x64-msvc": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@ast-grep/cli-win32-x64-msvc/-/cli-win32-x64-msvc-0.20.2.tgz", - "integrity": "sha512-j25nRYCD1qItZYPagWMqQCwHt8MyEUEFYXMJnQDbieS5OwKz98ErC3TnlRa3XRWGEk/4tIldzTGNQlAGpQKMYQ==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/@ast-grep/cli-win32-x64-msvc/-/cli-win32-x64-msvc-0.26.3.tgz", + "integrity": "sha512-gGX0AR4bpge4ITSD2I/6FaLtzeovujSVvkSSKTjI6PCZx6MMvJ3+8zcXEgwJSib7SliVquhabePjBpF4DLBC6g==", "cpu": [ "x64" ], diff --git a/package.json b/package.json index ee4c8bcc..bb3dd417 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,6 @@ "author": "", "license": "ISC", "devDependencies": { - "@ast-grep/cli": "^0.20.2" + "@ast-grep/cli": "^0.26.0" } -} +} \ No newline at end of file diff --git a/rules/c/security/libxml2-audit-parser-c.yml b/rules/c/security/libxml2-audit-parser-c.yml new file mode 100644 index 00000000..81d9c7f2 --- /dev/null +++ b/rules/c/security/libxml2-audit-parser-c.yml @@ -0,0 +1,25 @@ +id: libxml2-audit-parser-c +language: c +severity: warning +message: >- + The libxml2 library is used to parse XML. When auditing such code, make + sure that either the document being parsed is trusted or that the parsing + options are safe to consume untrusted documents. In such case make sure + DTD or XInclude documents cannot be loaded and there is no network access. +note: >- + [CWE-611] Improper Restriction of XML External Entity Reference. + [REFERENCES] + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration +rule: + any: + - pattern: xmlParseInNodeContext($CUR, $SRC, $DATALEN, $XML_OPTIONS, $LST) + - pattern: xmlReadDoc($CUR, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlReadFd($FD, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlReadFile($SRC, $ENC, $XML_OPTIONS) + - pattern: xmlReadIO($IO_READ, $IO_CLOSE, $IO_CTX, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlReadMemory($SRC, $SIZE, $URL, $ENC, $XML_OPTIONS) + - pattern: xmlCtxtReadDoc($CTX, $CUR, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlCtxtReadFd($CTX, $FD, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlCtxtReadFile($CTX, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlCtxtReadIO($CTX, $IO_READ, $IO_CLOSE, $IO_CTX, $SRC, $ENC,$XML_OPTIONS) + - pattern: xmlCtxtReadMemory($CTX, $SRC, $SIZE, $URL, $ENC, $XML_OPTIONS) diff --git a/rules/c/security/sizeof-this-c.yml b/rules/c/security/sizeof-this-c.yml new file mode 100644 index 00000000..bb024aa2 --- /dev/null +++ b/rules/c/security/sizeof-this-c.yml @@ -0,0 +1,13 @@ +id: sizeof-this-c +language: c +severity: warning +message: >- + Do not use `sizeof(this)` to get the number of bytes of the object in + memory. It returns the size of the pointer, not the size of the object. +note: >- + [CWE-467]: Use of sizeof() on a Pointer Type + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/ARR01-C.+Do+not+apply+the+sizeof+operator+to+a+pointer+when+taking+the+size+of+an+array +rule: + any: + - pattern: "sizeof(this)" diff --git a/rules/cpp/security/libxml2-audit-parser-cpp.yml b/rules/cpp/security/libxml2-audit-parser-cpp.yml new file mode 100644 index 00000000..84ee43f9 --- /dev/null +++ b/rules/cpp/security/libxml2-audit-parser-cpp.yml @@ -0,0 +1,25 @@ +id: libxml2-audit-parser-cpp +language: Cpp +severity: warning +message: >- + The libxml2 library is used to parse XML. When auditing such code, make + sure that either the document being parsed is trusted or that the parsing + options are safe to consume untrusted documents. In such case make sure + DTD or XInclude documents cannot be loaded and there is no network access. +note: >- + [CWE-611] Improper Restriction of XML External Entity Reference. + [REFERENCES] + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration +rule: + any: + - pattern: xmlParseInNodeContext($CUR, $SRC, $DATALEN, $XML_OPTIONS, $LST) + - pattern: xmlReadDoc($CUR, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlReadFd($FD, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlReadFile($SRC, $ENC, $XML_OPTIONS) + - pattern: xmlReadIO($IO_READ, $IO_CLOSE, $IO_CTX, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlReadMemory($SRC, $SIZE, $URL, $ENC, $XML_OPTIONS) + - pattern: xmlCtxtReadDoc($CTX, $CUR, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlCtxtReadFd($CTX, $FD, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlCtxtReadFile($CTX, $SRC, $ENC, $XML_OPTIONS) + - pattern: xmlCtxtReadIO($CTX, $IO_READ, $IO_CLOSE, $IO_CTX, $SRC, $ENC,$XML_OPTIONS) + - pattern: xmlCtxtReadMemory($CTX, $SRC, $SIZE, $URL, $ENC, $XML_OPTIONS) diff --git a/rules/csharp/security/httponly-false-csharp.yml b/rules/csharp/security/httponly-false-csharp.yml new file mode 100644 index 00000000..f874ec84 --- /dev/null +++ b/rules/csharp/security/httponly-false-csharp.yml @@ -0,0 +1,25 @@ +id: httponly-false-csharp +language: csharp +severity: warning +message: >- + "Detected a cookie where the `HttpOnly` flag is either missing or + disabled. The `HttpOnly` cookie flag instructs the browser to forbid + client-side JavaScript to read the cookie. If JavaScript interaction is + required, you can ignore this finding. However, set the `HttpOnly` flag to + `true` in all other cases. If this wasn't intentional, it's recommended to + set the HttpOnly flag to true so the cookie will not be accessible through + client-side scripts or to use the Cookie Policy Middleware to globally set + the HttpOnly flag. You can then use the CookieOptions class when + instantiating the cookie, which inherits these settings and will require + future developers to have to explicitly override them on a case-by-case + basis if needed. This approach ensures cookies are secure by default." +note: >- + [CWE-1004] Sensitive Cookie Without 'HttpOnly' Flag" + [REFERENCES] + - https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-8.0#cookie-policy-middleware + - https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.cookieoptions + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration +rule: + any: + - pattern: $BUILDER.Cookie.HttpOnly = false; + - pattern: $COOKIE.HttpOnly = false; diff --git a/rules/html/security/plaintext-http-link-html.yml b/rules/html/security/plaintext-http-link-html.yml new file mode 100644 index 00000000..0e0dbfb7 --- /dev/null +++ b/rules/html/security/plaintext-http-link-html.yml @@ -0,0 +1,14 @@ +id: plaintext-http-link-html +language: html +severity: warning +message: >- + "This link points to a plaintext HTTP URL. Prefer an encrypted HTTPS URL if possible." +note: >- + [CWE-319] Authentication Bypass by Primary Weakness + [REFERENCES] + - https://cwe.mitre.org/data/definitions/319.html +rule: + pattern: $C +constraints: + URL: + regex: ^['"`]?([Hh][Tt][Tt][Pp]://) diff --git a/rules/java/security/cbc-padding-oracle-java.yml b/rules/java/security/cbc-padding-oracle-java.yml new file mode 100644 index 00000000..78f11cef --- /dev/null +++ b/rules/java/security/cbc-padding-oracle-java.yml @@ -0,0 +1,17 @@ +id: cbc-padding-oracle-java +severity: warning +language: java +message: >- + Using CBC with PKCS5Padding is susceptible to padding oracle attacks. A + malicious actor could discern the difference between plaintext with valid + or invalid padding. Further, CBC mode does not include any integrity + checks. Use 'AES/GCM/NoPadding' instead. +note: >- + [CWE-327] Use of a Broken or Risky Cryptographic Algorithm. + [REFERENCES] + - https://capec.mitre.org/data/definitions/463.html +rule: + pattern: Cipher.getInstance($MODE) +constraints: + MODE: + regex: ".*/CBC/PKCS5Padding" diff --git a/rules/java/security/cbc-padding-oracle.yml b/rules/java/security/cbc-padding-oracle.yml deleted file mode 100644 index 0cb62145..00000000 --- a/rules/java/security/cbc-padding-oracle.yml +++ /dev/null @@ -1,16 +0,0 @@ -id: cbd-padding-oracle -severity: warning -language: java -message: >- - Using CBC with PKCS5Padding is susceptible to padding oracle attacks. - Use a secure mode of operation like GCM or CCM instead. -note: >- - [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm - [OWASP A03:2017]: Sensitive Data Exposure - [OWASP A02:2021]: Cryptographic Failures - [REFERENCES] - - https://capec.mitre.org/data/definitions/463.html - - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#cipher-modes - - https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY -rule: - pattern: Cipher.getInstance("AES/CBC/PKCS5Padding") \ No newline at end of file diff --git a/rules/java/security/cookie-secure-flag-false-java.yml b/rules/java/security/cookie-secure-flag-false-java.yml new file mode 100644 index 00000000..cd5418f4 --- /dev/null +++ b/rules/java/security/cookie-secure-flag-false-java.yml @@ -0,0 +1,14 @@ +id: cookie-secure-flag-false-java +language: java +severity: warning +message: >- + A cookie was detected without setting the 'secure' flag. The 'secure' + flag for cookies prevents the client from transmitting the cookie over + insecure channels such as HTTP. Set the 'secure' flag by calling + '$COOKIE.setSecure(true);'. +note: >- + [CWE-614] Sensitive Cookie in HTTPS Session Without 'Secure' Attribute. + [REFERENCES] + - https://owasp.org/www-community/controls/SecureCookieAttribute +rule: + pattern: $COOKIE.setSecure(false); diff --git a/rules/java/security/des-is-deprecated-java.yml b/rules/java/security/des-is-deprecated-java.yml new file mode 100644 index 00000000..8ce1895b --- /dev/null +++ b/rules/java/security/des-is-deprecated-java.yml @@ -0,0 +1,16 @@ +id: des-is-deprecated-java +severity: warning +language: java +message: >- + DES is considered deprecated. AES is the recommended cipher. Upgrade to + use AES. See https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard + for more information. +note: >- + [CWE-326] Inadequate Encryption Strength. + [REFERENCES] + - https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard +rule: + pattern: $CIPHER.getInstance($SAS) +constraints: + SAS: + regex: "DES" diff --git a/rules/java/security/desede-is-deprecated-java.yml b/rules/java/security/desede-is-deprecated-java.yml new file mode 100644 index 00000000..6db7b4c9 --- /dev/null +++ b/rules/java/security/desede-is-deprecated-java.yml @@ -0,0 +1,16 @@ +id: desede-is-deprecated-java +language: java +severity: warning +message: >- + Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. Upgrade to use AES. +note: >- + [CWE-326]: Inadequate Encryption Strength + [OWASP A03:2017]: Sensitive Data Exposure + [OWASP A02:2021]: Cryptographic Failures + [REFERENCES] + - https://find-sec-bugs.github.io/bugs.htm#TDES_USAGE + - https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA +rule: + any: + - pattern: $CIPHER.getInstance("=~/DESede.*/") + - pattern: $CRYPTO.KeyGenerator.getInstance("DES") diff --git a/rules/java/security/documentbuilderfactory-external-general-entities-true-java.yml b/rules/java/security/documentbuilderfactory-external-general-entities-true-java.yml new file mode 100644 index 00000000..6599fe87 --- /dev/null +++ b/rules/java/security/documentbuilderfactory-external-general-entities-true-java.yml @@ -0,0 +1,16 @@ +id: documentbuilderfactory-external-general-entities-true-java +language: java +severity: warning +message: >- + External entities are allowed for $DBFACTORY. This is vulnerable to XML + external entity attacks. Disable this by setting the feature + "http://xml.org/sax/features/external-general-entities" to false. +note: >- + [CWE-798]: Use of Hard-coded Credentials + [OWASP A07:2021]: Identification and Authentication Failures + [REFERENCES] + - https://blog.sonarsource.com/secure-xml-processor +rule: + pattern: + $DBFACTORY.setFeature("http://xml.org/sax/features/external-general-entities", + true); diff --git a/rules/java/security/ecb-cipher-java.yml b/rules/java/security/ecb-cipher-java.yml new file mode 100644 index 00000000..1ab3a112 --- /dev/null +++ b/rules/java/security/ecb-cipher-java.yml @@ -0,0 +1,17 @@ +id: ecb-cipher-java +severity: warning +language: java +message: >- + Cipher in ECB mode is detected. ECB mode produces the same output for + the same input each time which allows an attacker to intercept and replay + the data. Further, ECB mode does not provide any integrity checking. See + https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY. +note: >- + [CWE-327] Use of a Broken or Risky Cryptographic Algorithm. + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + pattern: Cipher $VAR = $CIPHER.getInstance($MODE); +constraints: + MODE: + regex: .*ECB.* diff --git a/rules/java/security/no-null-cipher-java.yml b/rules/java/security/no-null-cipher-java.yml new file mode 100644 index 00000000..b5eee11a --- /dev/null +++ b/rules/java/security/no-null-cipher-java.yml @@ -0,0 +1,17 @@ +id: no-null-cipher-java +severity: warning +language: java +message: >- + NullCipher was detected. This will not encrypt anything; the cipher + text will be the same as the plain text. Use a valid, secure cipher: + Cipher.getInstance("AES/CBC/PKCS7PADDING"). See + https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information. +note: >- + [CWE-327] Use of a Broken or Risky Cryptographic Algorithm. + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + any: + - pattern: new NullCipher($$$) + - pattern: new javax.crypto.NullCipher($$$) diff --git a/rules/java/security/rsa-no-padding-java.yml b/rules/java/security/rsa-no-padding-java.yml new file mode 100644 index 00000000..c9466216 --- /dev/null +++ b/rules/java/security/rsa-no-padding-java.yml @@ -0,0 +1,14 @@ +id: rsa-no-padding-java +severity: warning +language: java +message: >- + Using RSA without OAEP mode weakens the encryption. +note: >- + [CWE-326] Inadequate Encryption Strength + [REFERENCES] + - https://rdist.root.org/2009/10/06/why-rsa-encryption-padding-is-critical/ +rule: + pattern: $YST.getInstance($MODE) +constraints: + MODE: + regex: "RSA/[Nn][Oo][Nn][Ee]/NoPadding" diff --git a/rules/java/security/system-setproperty-hardcoded-secret-java.yml b/rules/java/security/system-setproperty-hardcoded-secret-java.yml new file mode 100644 index 00000000..537a16a3 --- /dev/null +++ b/rules/java/security/system-setproperty-hardcoded-secret-java.yml @@ -0,0 +1,22 @@ +id: system-setproperty-hardcoded-secret-java +language: java +severity: warning +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. Use + environment variables to securely provide credentials and other secrets or + retrieve them from a secure vault or Hardware Security Module (HSM). +note: >- + [CWE-798]: Use of Hard-coded Credentials + [OWASP A07:2021]: Identification and Authentication Failures + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +rule: + all: + - any: + - pattern: System.setProperty("javax.net.ssl.keyStorePassword", $PWD); + - pattern: System.setProperty("javax.net.ssl.trustStorePassword", $PWD); +constraints: + PWD: + regex: '^"' diff --git a/rules/java/security/unencrypted-socket-java.yml b/rules/java/security/unencrypted-socket-java.yml new file mode 100644 index 00000000..2b8540a5 --- /dev/null +++ b/rules/java/security/unencrypted-socket-java.yml @@ -0,0 +1,16 @@ +id: unencrypted-socket-java +language: java +severity: info +message: >- + "Detected use of a Java socket that is not encrypted. As a result, the + traffic could be read by an attacker intercepting the network traffic. Use + an SSLSocket created by 'SSLSocketFactory' or 'SSLServerSocketFactory' + instead." +note: >- + [CWE-319] Cleartext Transmission of Sensitive Information + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + any: + - pattern: new ServerSocket($$$) + - pattern: new Socket($$$) diff --git a/rules/java/security/use-of-aes-ecb-java.yml b/rules/java/security/use-of-aes-ecb-java.yml new file mode 100644 index 00000000..9e28e0b2 --- /dev/null +++ b/rules/java/security/use-of-aes-ecb-java.yml @@ -0,0 +1,22 @@ +id: use-of-aes-ecb-java +language: java +severity: warning +message: >- + Use of AES with ECB mode detected. ECB doesn't provide message + confidentiality and is not semantically secure so should not be used. + Instead, use a strong, secure cipher: + Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See + https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information. +note: >- + [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm + [OWASP A03:2017]: Sensitive Data Exposure + [OWASP A02:2021]: Cryptographic Failures + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html +rule: + pattern: $CIPHER.getInstance($MATCHES) +constraints: + MATCHES: + regex: ".*AES/ECB/.*" diff --git a/rules/java/security/use-of-blowfish-java.yml b/rules/java/security/use-of-blowfish-java.yml new file mode 100644 index 00000000..512745a2 --- /dev/null +++ b/rules/java/security/use-of-blowfish-java.yml @@ -0,0 +1,17 @@ +id: use-of-blowfish-java +language: java +severity: info +message: >- + Use of Blowfish was detected. Blowfish uses a 64-bit block size + that makes it vulnerable to birthday attacks, and is therefore considered + non-compliant. Instead, use a strong, secure cipher: + Cipher.getInstance("AES/CBC/PKCS7PADDING"). See + https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information. +note: >- + [CWE-327] Use of a Broken or Risky Cryptographic Algorithm + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html +rule: + pattern: $CIPHER.getInstance("Blowfish") diff --git a/rules/java/security/use-of-md5-digest-utils-java.yml b/rules/java/security/use-of-md5-digest-utils-java.yml new file mode 100644 index 00000000..77778a46 --- /dev/null +++ b/rules/java/security/use-of-md5-digest-utils-java.yml @@ -0,0 +1,13 @@ +id: use-of-md5-digest-utils-java +language: java +severity: warning +message: >- + 'Detected MD5 hash algorithm which is considered insecure. MD5 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use HMAC instead.' +note: >- + [CWE-328] Use of Weak Hash + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + pattern: DigestUtils.getMd5Digest($$$).digest($$$) diff --git a/rules/java/security/use-of-md5-java.yml b/rules/java/security/use-of-md5-java.yml new file mode 100644 index 00000000..a7835c21 --- /dev/null +++ b/rules/java/security/use-of-md5-java.yml @@ -0,0 +1,20 @@ +id: use-of-md5-java +severity: warning +language: java +message: >- + Detected MD5 hash algorithm which is considered insecure. MD5 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use HMAC instead. +note: >- + [CWE-328] Use of Weak Hash. + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + any: + - pattern: java.security.MessageDigest.getInstance($ALGO) + - pattern: java.security.MessageDigest.getInstance($ALGO, $$$) + - pattern: MessageDigest.getInstance($ALGO) + - pattern: MessageDigest.getInstance($ALGO, $$$) +constraints: + ALGO: + regex: "MD5" diff --git a/rules/java/security/use-of-rc2-java.yml b/rules/java/security/use-of-rc2-java.yml new file mode 100644 index 00000000..ad7a2401 --- /dev/null +++ b/rules/java/security/use-of-rc2-java.yml @@ -0,0 +1,13 @@ +id: use-of-rc2-java +language: java +severity: warning +message: >- + Use of RC2 was detected. RC2 is vulnerable to related-key attacks, and + is therefore considered non-compliant. Instead, use a strong, secure. +note: >- + [CWE-327] Use of a Broken or Risky Cryptographic Algorithm. + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html +rule: + pattern: $CIPHER.getInstance("RC2") diff --git a/rules/java/security/use-of-rc4-java.yml b/rules/java/security/use-of-rc4-java.yml new file mode 100644 index 00000000..2356d208 --- /dev/null +++ b/rules/java/security/use-of-rc4-java.yml @@ -0,0 +1,16 @@ +id: use-of-rc4-java +language: java +severity: warning +message: >- + 'Use of RC4 was detected. RC4 is vulnerable to several attacks, + including stream cipher attacks and bit flipping attacks. Instead, use a + strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See + https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information.' +note: >- + [CWE-327] Use of a Broken or Risky Cryptographic Algorithm + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html +rule: + pattern: $CIPHER.getInstance("RC4") diff --git a/rules/java/security/use-of-sha1-java.yml b/rules/java/security/use-of-sha1-java.yml new file mode 100644 index 00000000..1c24f3e3 --- /dev/null +++ b/rules/java/security/use-of-sha1-java.yml @@ -0,0 +1,20 @@ +id: use-of-sha1-java +language: java +severity: warning +message: >- + Detected SHA1 hash algorithm which is considered insecure. SHA1 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Instead, use PBKDF2 for password hashing or SHA256 or SHA512 + for other hash function applications. +note: >- + [CWE-328] Use of Weak Hash. + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + any: + - pattern: $DU.getSha1Digest().digest($$$) + - pattern: MessageDigest.getInstance($ALGO) + - pattern: java.security.MessageDigest.getInstance($ALGO,$$$) +constraints: + ALGO: + regex: "SHA1|SHA-1" diff --git a/rules/java/security/use-of-weak-rsa-key-java.yml b/rules/java/security/use-of-weak-rsa-key-java.yml new file mode 100644 index 00000000..8f7c96aa --- /dev/null +++ b/rules/java/security/use-of-weak-rsa-key-java.yml @@ -0,0 +1,16 @@ +id: use-of-weak-rsa-key-java +language: java +severity: warning +message: >- + RSA keys should be at least 2048 bits based on NIST recommendation. +note: >- + [CWE-326] Inadequate Encryption Strength. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms +rule: + pattern: | + $KEY.initialize($AST) +follows: KeyPairGenerator $KEY = $G.getInstance("RSA"); +constraints: + AST: + regex: '^(-?(0|[1-9][0-9]?|[1-9][0-9]{2}|1[0-9]{3}|20[0-3][0-9]|204[0-7])(\.[0-9]+)?|0|-[1-9][0-9]*|-[1-9][0-9]{2,}|-1[0-9]{3}|-20[0-3][0-9]|-204[0-7])$' diff --git a/rules/java/security/weak-ssl-context-java.yml b/rules/java/security/weak-ssl-context-java.yml new file mode 100644 index 00000000..411ca262 --- /dev/null +++ b/rules/java/security/weak-ssl-context-java.yml @@ -0,0 +1,22 @@ +id: weak-ssl-context-java +language: java +severity: warning +message: >- + 'An insecure SSL context was detected. TLS versions 1.0, 1.1, and all + SSL versions are considered weak encryption and are deprecated. Use + SSLContext.getInstance("TLSv1.2") for the best security.' +note: >- + [CWE-326] Inadequate Encryption Strength + [REFERENCES] + - https://tools.ietf.org/html/rfc7568 + - https://tools.ietf.org/id/draft-ietf-tls-oldversions-deprecate-02.html +rule: + all: + - pattern: SSLContext.getInstance($CONTEXT) + - not: + pattern: SSLContext.getInstance("TLSv1.3") + - not: + pattern: SSLContext.getInstance("TLSv1.2") +constraints: + CONTEXT: + regex: (TLS|SSL) diff --git a/rules/kotlin/security/des-is-deprecated-kotlin.yml b/rules/kotlin/security/des-is-deprecated-kotlin.yml new file mode 100644 index 00000000..377e3ed5 --- /dev/null +++ b/rules/kotlin/security/des-is-deprecated-kotlin.yml @@ -0,0 +1,16 @@ +id: des-is-deprecated-kotlin +severity: warning +language: kotlin +message: >- + DES is considered deprecated. AES is the recommended cipher. Upgrade to + use AES. See https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard + for more information. +note: >- + [CWE-326] Inadequate Encryption Strength. + [REFERENCES] + - https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard +rule: + pattern: $CIPHER.getInstance($SAS) +constraints: + SAS: + regex: "DES" diff --git a/rules/kotlin/security/desede-is-deprecated-kotlin.yml b/rules/kotlin/security/desede-is-deprecated-kotlin.yml new file mode 100644 index 00000000..f0a7351a --- /dev/null +++ b/rules/kotlin/security/desede-is-deprecated-kotlin.yml @@ -0,0 +1,16 @@ +id: desede-is-deprecated-kotlin +language: kotlin +severity: warning +message: >- + Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. Upgrade to use AES. +note: >- + [CWE-326]: Inadequate Encryption Strength + [OWASP A03:2017]: Sensitive Data Exposure + [OWASP A02:2021]: Cryptographic Failures + [REFERENCES] + - https://find-sec-bugs.github.io/bugs.htm#TDES_USAGE + - https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA +rule: + any: + - pattern: $CIPHER.getInstance("=~/DESede.*/") + - pattern: $CRYPTO.KeyGenerator.getInstance("DES") diff --git a/rules/kotlin/security/rsa-no-padding-kotlin.yml b/rules/kotlin/security/rsa-no-padding-kotlin.yml new file mode 100644 index 00000000..49e07e7b --- /dev/null +++ b/rules/kotlin/security/rsa-no-padding-kotlin.yml @@ -0,0 +1,14 @@ +id: rsa-no-padding-kotlin +severity: warning +language: kotlin +message: >- + Using RSA without OAEP mode weakens the encryption. +note: >- + [CWE-326] Inadequate Encryption Strength + [REFERENCES] + - https://rdist.root.org/2009/10/06/why-rsa-encryption-padding-is-critical/ +rule: + pattern: $YST.getInstance($MODE) +constraints: + MODE: + regex: "RSA/[Nn][Oo][Nn][Ee]/NoPadding" diff --git a/rules/kotlin/security/system-setproperty-hardcoded-secret-kotlin.yml b/rules/kotlin/security/system-setproperty-hardcoded-secret-kotlin.yml new file mode 100644 index 00000000..06635555 --- /dev/null +++ b/rules/kotlin/security/system-setproperty-hardcoded-secret-kotlin.yml @@ -0,0 +1,22 @@ +id: system-setproperty-hardcoded-secret-kotlin +language: kotlin +severity: warning +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. Use + environment variables to securely provide credentials and other secrets or + retrieve them from a secure vault or Hardware Security Module (HSM). +note: >- + [CWE-798]: Use of Hard-coded Credentials + [OWASP A07:2021]: Identification and Authentication Failures + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +rule: + all: + - any: + - pattern: System.setProperty("javax.net.ssl.keyStorePassword", $PWD); + - pattern: System.setProperty("javax.net.ssl.trustStorePassword", $PWD); +constraints: + PWD: + regex: '^"' diff --git a/rules/kotlin/security/use-of-weak-rsa-key-kotlin.yml b/rules/kotlin/security/use-of-weak-rsa-key-kotlin.yml new file mode 100644 index 00000000..1620ce16 --- /dev/null +++ b/rules/kotlin/security/use-of-weak-rsa-key-kotlin.yml @@ -0,0 +1,18 @@ +id: use-of-weak-rsa-key-kotlin +language: kotlin +severity: warning +message: >- + RSA keys should be at least 2048 bits based on NIST recommendation +note: >- + [CWE-326]: Inadequate Encryption Strength + [OWASP A03:2017]: Sensitive Data Exposure + [OWASP A02:2021]: Cryptographic Failures + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms +rule: + pattern: | + $KEY.initialize($BITS) +follows: KEY = $G.getInstance("RSA"); +constraints: + BITS: + regex: '^(-?(0|[1-9][0-9]?|[1-9][0-9]{2}|1[0-9]{3}|20[0-3][0-9]|204[0-7])(\.[0-9]+)?|0|-[1-9][0-9]*|-[1-9][0-9]{2,}|-1[0-9]{3}|-20[0-3][0-9]|-204[0-7])$' diff --git a/rules/rust/security/reqwest-accept-invalid-rust.yml b/rules/rust/security/reqwest-accept-invalid-rust.yml new file mode 100644 index 00000000..27fc9d8b --- /dev/null +++ b/rules/rust/security/reqwest-accept-invalid-rust.yml @@ -0,0 +1,17 @@ +id: reqwest-accept-invalid-rust +language: rust +severity: warning +message: >- + Dangerously accepting invalid TLS +note: >- + [CWE-295]: Improper Certificate + [REFERENCES] + - https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html#method.danger_accept_invalid_hostnames + - https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html#method.danger_accept_invalid_certs +rule: + any: + - pattern: $CLIENT.danger_accept_invalid_hostnames(true) + - pattern: $CLIENT.danger_accept_invalid_certs(true) +constraints: + CLIENT: + regex: '^reqwest::Client::builder\(\)' diff --git a/rules/scala/security/rsa-padding-set-scala.yml b/rules/scala/security/rsa-padding-set-scala.yml new file mode 100644 index 00000000..b4601500 --- /dev/null +++ b/rules/scala/security/rsa-padding-set-scala.yml @@ -0,0 +1,18 @@ +id: rsa-padding-set-scala +language: scala +severity: warning +message: >- + Usage of RSA without OAEP (Optimal Asymmetric Encryption Padding) may + weaken encryption. This could lead to sensitive data exposure. Instead, + use RSA with `OAEPWithMD5AndMGF1Padding` instead. + +note: >- + [CWE-780] Use of RSA Algorithm without OAEP + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + any: + - pattern: $CIPHER.getInstance($MODE) +constraints: + MODE: + regex: ".*RSA/.*/NoPadding.*" diff --git a/rules/scala/security/xmlinputfactory-dtd-enabled-scala.yml b/rules/scala/security/xmlinputfactory-dtd-enabled-scala.yml new file mode 100644 index 00000000..732fddc9 --- /dev/null +++ b/rules/scala/security/xmlinputfactory-dtd-enabled-scala.yml @@ -0,0 +1,22 @@ +id: xmlinputfactory-dtd-enabled-scala +language: scala +severity: warning +message: >- + XMLInputFactory being instantiated without calling the setProperty + functions that are generally used for disabling entity processing. User + controlled data in XML Document builder can result in XML Internal Entity + Processing vulnerabilities like the disclosure of confidential data, + denial of service, Server Side Request Forgery (SSRF), port scanning. Make + sure to disable entity processing functionality. +note: >- + [CWE-611] Improper Restriction of XML External Entity. + [REFERENCES] + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration +rule: + any: + - pattern: XMLInputFactory.newFactory($$$) + - pattern: XMLInputFactory.newInstance($$$) + - pattern: new XMLInputFactory($$$) +precedes: + not: + pattern: $XMLFACTORY.setProperty(javax.xml.stream.isSupportingExternalEntities, false) diff --git a/rules/swift/security/insecure-biometrics-swift.yml b/rules/swift/security/insecure-biometrics-swift.yml new file mode 100644 index 00000000..8ea5a821 --- /dev/null +++ b/rules/swift/security/insecure-biometrics-swift.yml @@ -0,0 +1,19 @@ +id: insecure-biometrics-swift +language: swift +severity: info +message: >- + The application was observed to leverage biometrics via Local + Authentication, which returns a simple boolean result for authentication. + This design is subject to bypass with runtime tampering tools such as + Frida, Substrate, and others. Although this is limited to rooted + (jailbroken) devices, consider implementing biometric authentication the + reliable way - via Keychain Services. +note: >- + [CWE-305] Authentication Bypass by Primary Weakness + [REFERENCES] + - https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06f-testing-local-authentication + - https://shirazkhan030.medium.com/biometric-authentication-in-ios-6c53c54f17df +rule: + any: + - pattern: LAContext.evaluatePolicy + - pattern: $X.evaluatePolicy diff --git a/tests/__snapshots__/cbc-padding-oracle-java-snapshot.yml b/tests/__snapshots__/cbc-padding-oracle-java-snapshot.yml new file mode 100644 index 00000000..12d32ee1 --- /dev/null +++ b/tests/__snapshots__/cbc-padding-oracle-java-snapshot.yml @@ -0,0 +1,15 @@ +id: cbc-padding-oracle-java +snapshots: + Cipher.getInstance("AES/CBC/PKCS5Padding");: + labels: + - source: Cipher.getInstance("AES/CBC/PKCS5Padding") + style: primary + start: 0 + end: 42 + ? | + Cipher.getInstance("AES/CBC/PKCS5Padding"); + : labels: + - source: Cipher.getInstance("AES/CBC/PKCS5Padding") + style: primary + start: 0 + end: 42 diff --git a/tests/__snapshots__/cookie-secure-flag-false-java-snapshot.yml b/tests/__snapshots__/cookie-secure-flag-false-java-snapshot.yml new file mode 100644 index 00000000..b4c1bec6 --- /dev/null +++ b/tests/__snapshots__/cookie-secure-flag-false-java-snapshot.yml @@ -0,0 +1,9 @@ +id: cookie-secure-flag-false-java +snapshots: + ? | + cookie.setSecure(false); + : labels: + - source: cookie.setSecure(false); + style: primary + start: 0 + end: 24 diff --git a/tests/__snapshots__/des-is-deprecated-java-snapshot.yml b/tests/__snapshots__/des-is-deprecated-java-snapshot.yml new file mode 100644 index 00000000..35070ef2 --- /dev/null +++ b/tests/__snapshots__/des-is-deprecated-java-snapshot.yml @@ -0,0 +1,9 @@ +id: des-is-deprecated-java +snapshots: + ? | + Cipher.getInstance("DES/ECB/PKCS5Padding"); + : labels: + - source: Cipher.getInstance("DES/ECB/PKCS5Padding") + style: primary + start: 0 + end: 42 diff --git a/tests/__snapshots__/des-is-deprecated-kotlin-snapshot.yml b/tests/__snapshots__/des-is-deprecated-kotlin-snapshot.yml new file mode 100644 index 00000000..ebce9bbf --- /dev/null +++ b/tests/__snapshots__/des-is-deprecated-kotlin-snapshot.yml @@ -0,0 +1,9 @@ +id: des-is-deprecated-kotlin +snapshots: + ? | + Cipher.getInstance("DES/ECB/PKCS5Padding"); + : labels: + - source: Cipher.getInstance("DES/ECB/PKCS5Padding") + style: primary + start: 0 + end: 42 diff --git a/tests/__snapshots__/desede-is-deprecated-java-snapshot.yml b/tests/__snapshots__/desede-is-deprecated-java-snapshot.yml new file mode 100644 index 00000000..1b0bc359 --- /dev/null +++ b/tests/__snapshots__/desede-is-deprecated-java-snapshot.yml @@ -0,0 +1,10 @@ +id: desede-is-deprecated-java +snapshots: + ? | + Cipher.getInstance("DESede/ECB/PKCS5Padding"); + javax.crypto.KeyGenerator.getInstance("DES") + : labels: + - source: javax.crypto.KeyGenerator.getInstance("DES") + style: primary + start: 47 + end: 91 diff --git a/tests/__snapshots__/desede-is-deprecated-kotlin-snapshot.yml b/tests/__snapshots__/desede-is-deprecated-kotlin-snapshot.yml new file mode 100644 index 00000000..7eb1119d --- /dev/null +++ b/tests/__snapshots__/desede-is-deprecated-kotlin-snapshot.yml @@ -0,0 +1,10 @@ +id: desede-is-deprecated-kotlin +snapshots: + ? | + Cipher.getInstance("DESede/ECB/PKCS5Padding"); + javax.crypto.KeyGenerator.getInstance("DES") + : labels: + - source: javax.crypto.KeyGenerator.getInstance("DES") + style: primary + start: 47 + end: 91 diff --git a/tests/__snapshots__/documentbuilderfactory-external-general-entities-true-java-snapshot.yml b/tests/__snapshots__/documentbuilderfactory-external-general-entities-true-java-snapshot.yml new file mode 100644 index 00000000..238311e7 --- /dev/null +++ b/tests/__snapshots__/documentbuilderfactory-external-general-entities-true-java-snapshot.yml @@ -0,0 +1,10 @@ +id: documentbuilderfactory-external-general-entities-true-java +snapshots: + ? | + dbf.setFeature("http://xml.org/sax/features/external-general-entities" , true); + spf.setFeature("http://xml.org/sax/features/external-general-entities" , true); + : labels: + - source: dbf.setFeature("http://xml.org/sax/features/external-general-entities" , true); + style: primary + start: 0 + end: 79 diff --git a/tests/__snapshots__/ecb-cipher-java-snapshot.yml b/tests/__snapshots__/ecb-cipher-java-snapshot.yml new file mode 100644 index 00000000..a9c76fd2 --- /dev/null +++ b/tests/__snapshots__/ecb-cipher-java-snapshot.yml @@ -0,0 +1,9 @@ +id: ecb-cipher-java +snapshots: + ? | + Cipher c = Cipher.getInstance("AES/ECB/NoPadding"); + : labels: + - source: Cipher c = Cipher.getInstance("AES/ECB/NoPadding"); + style: primary + start: 0 + end: 51 diff --git a/tests/__snapshots__/httponly-false-csharp-snapshot.yml b/tests/__snapshots__/httponly-false-csharp-snapshot.yml new file mode 100644 index 00000000..4ec18734 --- /dev/null +++ b/tests/__snapshots__/httponly-false-csharp-snapshot.yml @@ -0,0 +1,16 @@ +id: httponly-false-csharp +snapshots: + ? | + myHttpOnlyCookie.HttpOnly = false; + : labels: + - source: myHttpOnlyCookie.HttpOnly = false; + style: primary + start: 0 + end: 34 + ? | + options.Cookie.HttpOnly = false; + : labels: + - source: options.Cookie.HttpOnly = false; + style: primary + start: 0 + end: 32 diff --git a/tests/__snapshots__/insecure-biometrics-swift-snapshot.yml b/tests/__snapshots__/insecure-biometrics-swift-snapshot.yml new file mode 100644 index 00000000..2e7ddc4c --- /dev/null +++ b/tests/__snapshots__/insecure-biometrics-swift-snapshot.yml @@ -0,0 +1,9 @@ +id: insecure-biometrics-swift +snapshots: + ? | + context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "Authenticate to the application" + : labels: + - source: context.evaluatePolicy + style: primary + start: 0 + end: 22 diff --git a/tests/__snapshots__/libxml2-audit-parser-c-snapshot.yml b/tests/__snapshots__/libxml2-audit-parser-c-snapshot.yml new file mode 100644 index 00000000..60994812 --- /dev/null +++ b/tests/__snapshots__/libxml2-audit-parser-c-snapshot.yml @@ -0,0 +1,12 @@ +id: libxml2-audit-parser-c +snapshots: + ? | + xmlParseInNodeContext(cur_node->parent, xml_filtered.c_str(), + (int)xml_filtered.length(), 0, &pNewNode); + : labels: + - source: |- + xmlParseInNodeContext(cur_node->parent, xml_filtered.c_str(), + (int)xml_filtered.length(), 0, &pNewNode) + style: primary + start: 0 + end: 103 diff --git a/tests/__snapshots__/libxml2-audit-parser-cpp-snapshot.yml b/tests/__snapshots__/libxml2-audit-parser-cpp-snapshot.yml new file mode 100644 index 00000000..6d424b83 --- /dev/null +++ b/tests/__snapshots__/libxml2-audit-parser-cpp-snapshot.yml @@ -0,0 +1,12 @@ +id: libxml2-audit-parser-cpp +snapshots: + ? | + xmlParseInNodeContext(cur_node->parent, xml_filtered.c_str(), + (int)xml_filtered.length(), 0, &pNewNode); + : labels: + - source: |- + xmlParseInNodeContext(cur_node->parent, xml_filtered.c_str(), + (int)xml_filtered.length(), 0, &pNewNode) + style: primary + start: 0 + end: 103 diff --git a/tests/__snapshots__/no-null-cipher-java-snapshot.yml b/tests/__snapshots__/no-null-cipher-java-snapshot.yml new file mode 100644 index 00000000..a926152d --- /dev/null +++ b/tests/__snapshots__/no-null-cipher-java-snapshot.yml @@ -0,0 +1,18 @@ +id: no-null-cipher-java +snapshots: + ? |- + Cipher doNothingCihper = new NullCipher(); + new javax.crypto.NullCipher(); + : labels: + - source: new NullCipher() + style: primary + start: 25 + end: 41 + ? | + Cipher doNothingCihper = new NullCipher(); + new javax.crypto.NullCipher(); + : labels: + - source: new NullCipher() + style: primary + start: 25 + end: 41 diff --git a/tests/__snapshots__/plaintext-http-link-html-snapshot.yml b/tests/__snapshots__/plaintext-http-link-html-snapshot.yml new file mode 100644 index 00000000..98516a80 --- /dev/null +++ b/tests/__snapshots__/plaintext-http-link-html-snapshot.yml @@ -0,0 +1,15 @@ +id: plaintext-http-link-html +snapshots: + ? | + Astgrep + Astgrep + Astgrep + Astgrep + Astgrep + Astgrep + Astgrep + : labels: + - source: Astgrep + style: primary + start: 0 + end: 40 diff --git a/tests/__snapshots__/reqwest-accept-invalid-rust-snapshot.yml b/tests/__snapshots__/reqwest-accept-invalid-rust-snapshot.yml new file mode 100644 index 00000000..cb1eeac4 --- /dev/null +++ b/tests/__snapshots__/reqwest-accept-invalid-rust-snapshot.yml @@ -0,0 +1,30 @@ +id: reqwest-accept-invalid-rust +snapshots: + ? | + reqwest::Client::builder().danger_accept_invalid_certs(true) + : labels: + - source: reqwest::Client::builder().danger_accept_invalid_certs(true) + style: primary + start: 0 + end: 60 + ? | + reqwest::Client::builder().danger_accept_invalid_hostnames(true) + : labels: + - source: reqwest::Client::builder().danger_accept_invalid_hostnames(true) + style: primary + start: 0 + end: 64 + ? | + reqwest::Client::builder().user_agent("USER AGENT").cookie_store(true).danger_accept_invalid_certs(true) + : labels: + - source: reqwest::Client::builder().user_agent("USER AGENT").cookie_store(true).danger_accept_invalid_certs(true) + style: primary + start: 0 + end: 104 + ? | + reqwest::Client::builder().user_agent("USER AGENT").cookie_store(true).danger_accept_invalid_hostnames(true) + : labels: + - source: reqwest::Client::builder().user_agent("USER AGENT").cookie_store(true).danger_accept_invalid_hostnames(true) + style: primary + start: 0 + end: 108 diff --git a/tests/__snapshots__/rsa-no-padding-java-snapshot.yml b/tests/__snapshots__/rsa-no-padding-java-snapshot.yml new file mode 100644 index 00000000..80e65e5d --- /dev/null +++ b/tests/__snapshots__/rsa-no-padding-java-snapshot.yml @@ -0,0 +1,18 @@ +id: rsa-no-padding-java +snapshots: + ? |- + Cipher.getInstance("RSA/None/NoPadding"); + Cipher.getInstance("RSA/NONE/NoPadding"); + : labels: + - source: Cipher.getInstance("RSA/None/NoPadding") + style: primary + start: 0 + end: 40 + ? | + Cipher.getInstance("RSA/None/NoPadding"); + Cipher.getInstance("RSA/NONE/NoPadding"); + : labels: + - source: Cipher.getInstance("RSA/None/NoPadding") + style: primary + start: 0 + end: 40 diff --git a/tests/__snapshots__/rsa-no-padding-kotlin-snapshot.yml b/tests/__snapshots__/rsa-no-padding-kotlin-snapshot.yml new file mode 100644 index 00000000..4507882d --- /dev/null +++ b/tests/__snapshots__/rsa-no-padding-kotlin-snapshot.yml @@ -0,0 +1,10 @@ +id: rsa-no-padding-kotlin +snapshots: + ? | + Cipher.getInstance("RSA/None/NoPadding"); + Cipher.getInstance("RSA/NONE/NoPadding"); + : labels: + - source: Cipher.getInstance("RSA/None/NoPadding") + style: primary + start: 0 + end: 40 diff --git a/tests/__snapshots__/rsa-padding-set-scala-snapshot.yml b/tests/__snapshots__/rsa-padding-set-scala-snapshot.yml new file mode 100644 index 00000000..1274abe0 --- /dev/null +++ b/tests/__snapshots__/rsa-padding-set-scala-snapshot.yml @@ -0,0 +1,15 @@ +id: rsa-padding-set-scala +snapshots: + Cipher.getInstance("RSA/ECB/NoPadding"): + labels: + - source: Cipher.getInstance("RSA/ECB/NoPadding") + style: primary + start: 0 + end: 39 + ? | + Cipher.getInstance("RSA/ECB/NoPadding") + : labels: + - source: Cipher.getInstance("RSA/ECB/NoPadding") + style: primary + start: 0 + end: 39 diff --git a/tests/__snapshots__/sizeof-this-c-snapshot.yml b/tests/__snapshots__/sizeof-this-c-snapshot.yml new file mode 100644 index 00000000..e8db9995 --- /dev/null +++ b/tests/__snapshots__/sizeof-this-c-snapshot.yml @@ -0,0 +1,9 @@ +id: sizeof-this-c +snapshots: + ? | + return sizeof(this); + : labels: + - source: sizeof(this) + style: primary + start: 7 + end: 19 diff --git a/tests/__snapshots__/system-setproperty-hardcoded-secret-java-snapshot.yml b/tests/__snapshots__/system-setproperty-hardcoded-secret-java-snapshot.yml new file mode 100644 index 00000000..9130101a --- /dev/null +++ b/tests/__snapshots__/system-setproperty-hardcoded-secret-java-snapshot.yml @@ -0,0 +1,10 @@ +id: system-setproperty-hardcoded-secret-java +snapshots: + ? | + System.setProperty("javax.net.ssl.keyStorePassword", "password"); + System.setProperty("javax.net.ssl.trustStorePassword", "password"); + : labels: + - source: System.setProperty("javax.net.ssl.keyStorePassword", "password"); + style: primary + start: 0 + end: 65 diff --git a/tests/__snapshots__/system-setproperty-hardcoded-secret-kotlin-snapshot.yml b/tests/__snapshots__/system-setproperty-hardcoded-secret-kotlin-snapshot.yml new file mode 100644 index 00000000..0d421bce --- /dev/null +++ b/tests/__snapshots__/system-setproperty-hardcoded-secret-kotlin-snapshot.yml @@ -0,0 +1,10 @@ +id: system-setproperty-hardcoded-secret-kotlin +snapshots: + ? | + System.setProperty("javax.net.ssl.keyStorePassword", "password"); + System.setProperty("javax.net.ssl.trustStorePassword", "password"); + : labels: + - source: System.setProperty("javax.net.ssl.keyStorePassword", "password") + style: primary + start: 0 + end: 64 diff --git a/tests/__snapshots__/unencrypted-socket-java-snapshot.yml b/tests/__snapshots__/unencrypted-socket-java-snapshot.yml new file mode 100644 index 00000000..e0becd2b --- /dev/null +++ b/tests/__snapshots__/unencrypted-socket-java-snapshot.yml @@ -0,0 +1,58 @@ +id: unencrypted-socket-java +snapshots: + ? | + ServerSocket ssoc = new ServerSocket(1234); + : labels: + - source: new ServerSocket(1234) + style: primary + start: 20 + end: 42 + ? | + ServerSocket ssoc1 = new ServerSocket(); + : labels: + - source: new ServerSocket() + style: primary + start: 21 + end: 39 + ? | + ServerSocket ssoc2 = new ServerSocket(1234, 10); + : labels: + - source: new ServerSocket(1234, 10) + style: primary + start: 21 + end: 47 + ? | + ServerSocket ssoc3 = new ServerSocket(1234, 10, InetAddress.getByAddress(address)); + : labels: + - source: new ServerSocket(1234, 10, InetAddress.getByAddress(address)) + style: primary + start: 21 + end: 82 + ? | + Socket soc = new Socket("www.google.com", 80); + : labels: + - source: new Socket("www.google.com", 80) + style: primary + start: 13 + end: 45 + ? | + Socket soc1 = new Socket("www.google.com", 80, true); + : labels: + - source: new Socket("www.google.com", 80, true) + style: primary + start: 14 + end: 52 + ? | + Socket soc2 = new Socket("www.google.com", 80, InetAddress.getByAddress(address), 13337); + : labels: + - source: new Socket("www.google.com", 80, InetAddress.getByAddress(address), 13337) + style: primary + start: 14 + end: 88 + ? | + Socket soc3 = new Socket(InetAddress.getByAddress(remoteAddress), 80); + : labels: + - source: new Socket(InetAddress.getByAddress(remoteAddress), 80) + style: primary + start: 14 + end: 69 diff --git a/tests/__snapshots__/use-of-aes-ecb-java-snapshot.yml b/tests/__snapshots__/use-of-aes-ecb-java-snapshot.yml new file mode 100644 index 00000000..6c8a701c --- /dev/null +++ b/tests/__snapshots__/use-of-aes-ecb-java-snapshot.yml @@ -0,0 +1,10 @@ +id: use-of-aes-ecb-java +snapshots: + ? | + Cipher.getInstance("AES/ECB/NoPadding") + Cipher.getInstance("AES/ECB/PKCS5Padding") + : labels: + - source: Cipher.getInstance("AES/ECB/NoPadding") + style: primary + start: 0 + end: 39 diff --git a/tests/__snapshots__/use-of-blowfish-java-snapshot.yml b/tests/__snapshots__/use-of-blowfish-java-snapshot.yml new file mode 100644 index 00000000..cc54e7fb --- /dev/null +++ b/tests/__snapshots__/use-of-blowfish-java-snapshot.yml @@ -0,0 +1,16 @@ +id: use-of-blowfish-java +snapshots: + ? | + Cipher.getInstance("Blowfish"); + : labels: + - source: Cipher.getInstance("Blowfish") + style: primary + start: 0 + end: 30 + ? | + useCipher(Cipher.getInstance("Blowfish")); + : labels: + - source: Cipher.getInstance("Blowfish") + style: primary + start: 10 + end: 40 diff --git a/tests/__snapshots__/use-of-md5-digest-utils-java-snapshot.yml b/tests/__snapshots__/use-of-md5-digest-utils-java-snapshot.yml new file mode 100644 index 00000000..fe41e08d --- /dev/null +++ b/tests/__snapshots__/use-of-md5-digest-utils-java-snapshot.yml @@ -0,0 +1,9 @@ +id: use-of-md5-digest-utils-java +snapshots: + ? | + byte[] hashValue = DigestUtils.getMd5Digest().digest(password.getBytes()); + : labels: + - source: DigestUtils.getMd5Digest().digest(password.getBytes()) + style: primary + start: 19 + end: 73 diff --git a/tests/__snapshots__/use-of-md5-java-snapshot.yml b/tests/__snapshots__/use-of-md5-java-snapshot.yml new file mode 100644 index 00000000..6f6c27ae --- /dev/null +++ b/tests/__snapshots__/use-of-md5-java-snapshot.yml @@ -0,0 +1,9 @@ +id: use-of-md5-java +snapshots: + ? | + MessageDigest md5Digest = MessageDigest.getInstance("MD5"); + : labels: + - source: MessageDigest.getInstance("MD5") + style: primary + start: 26 + end: 58 diff --git a/tests/__snapshots__/use-of-rc2-java-snapshot.yml b/tests/__snapshots__/use-of-rc2-java-snapshot.yml new file mode 100644 index 00000000..7ac4199f --- /dev/null +++ b/tests/__snapshots__/use-of-rc2-java-snapshot.yml @@ -0,0 +1,10 @@ +id: use-of-rc2-java +snapshots: + ? | + useCipher(Cipher.getInstance("RC2")); + Cipher.getInstance("RC2"); + : labels: + - source: Cipher.getInstance("RC2") + style: primary + start: 10 + end: 35 diff --git a/tests/__snapshots__/use-of-rc4-java-snapshot.yml b/tests/__snapshots__/use-of-rc4-java-snapshot.yml new file mode 100644 index 00000000..cbf4423c --- /dev/null +++ b/tests/__snapshots__/use-of-rc4-java-snapshot.yml @@ -0,0 +1,16 @@ +id: use-of-rc4-java +snapshots: + ? | + Cipher.getInstance("RC4"); + : labels: + - source: Cipher.getInstance("RC4") + style: primary + start: 0 + end: 25 + ? | + useCipher(Cipher.getInstance("RC4")); + : labels: + - source: Cipher.getInstance("RC4") + style: primary + start: 10 + end: 35 diff --git a/tests/__snapshots__/use-of-sha1-java-snapshot.yml b/tests/__snapshots__/use-of-sha1-java-snapshot.yml new file mode 100644 index 00000000..444fe5b3 --- /dev/null +++ b/tests/__snapshots__/use-of-sha1-java-snapshot.yml @@ -0,0 +1,10 @@ +id: use-of-sha1-java +snapshots: + ? | + java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA1", "SUN"); + DigestUtils.getSha1Digest().digest(password.getBytes()); + : labels: + - source: java.security.MessageDigest.getInstance("SHA1", "SUN") + style: primary + start: 33 + end: 87 diff --git a/tests/__snapshots__/use-of-weak-rsa-key-java-snapshot.yml b/tests/__snapshots__/use-of-weak-rsa-key-java-snapshot.yml new file mode 100644 index 00000000..bb83308a --- /dev/null +++ b/tests/__snapshots__/use-of-weak-rsa-key-java-snapshot.yml @@ -0,0 +1,34 @@ +id: use-of-weak-rsa-key-java +snapshots: + ? | + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(-512); + : labels: + - source: keyGen.initialize(-512) + style: primary + start: 63 + end: 86 + ? | + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(512); + : labels: + - source: keyGen.initialize(512) + style: primary + start: 63 + end: 85 + ? | + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(512.0); + : labels: + - source: keyGen.initialize(512.0) + style: primary + start: 63 + end: 87 + ? | + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(512.09); + : labels: + - source: keyGen.initialize(512.09) + style: primary + start: 63 + end: 88 diff --git a/tests/__snapshots__/use-of-weak-rsa-key-kotlin-snapshot.yml b/tests/__snapshots__/use-of-weak-rsa-key-kotlin-snapshot.yml new file mode 100644 index 00000000..5c7fe552 --- /dev/null +++ b/tests/__snapshots__/use-of-weak-rsa-key-kotlin-snapshot.yml @@ -0,0 +1,10 @@ +id: use-of-weak-rsa-key-kotlin +snapshots: + ? | + KeyPairGenerator.getInstance("RSA") + keyGen.initialize(-5.12); + : labels: + - source: keyGen.initialize(-5.12) + style: primary + start: 36 + end: 60 diff --git a/tests/__snapshots__/weak-ssl-context-java-snapshot.yml b/tests/__snapshots__/weak-ssl-context-java-snapshot.yml new file mode 100644 index 00000000..ca21f566 --- /dev/null +++ b/tests/__snapshots__/weak-ssl-context-java-snapshot.yml @@ -0,0 +1,37 @@ +id: weak-ssl-context-java +snapshots: + ? | + SSLContext ctx = SSLContext.getInstance("SSL"); + : labels: + - source: SSLContext.getInstance("SSL") + style: primary + start: 17 + end: 46 + ? | + SSLContext ctx = SSLContext.getInstance("SSLv3"); + : labels: + - source: SSLContext.getInstance("SSLv3") + style: primary + start: 17 + end: 48 + ? | + SSLContext ctx = SSLContext.getInstance("TLS"); + : labels: + - source: SSLContext.getInstance("TLS") + style: primary + start: 17 + end: 46 + ? | + SSLContext ctx = SSLContext.getInstance("TLSv1"); + : labels: + - source: SSLContext.getInstance("TLSv1") + style: primary + start: 17 + end: 48 + ? | + SSLContext ctx = SSLContext.getInstance("TLSv1.1"); + : labels: + - source: SSLContext.getInstance("TLSv1.1") + style: primary + start: 17 + end: 50 diff --git a/tests/__snapshots__/xmlinputfactory-dtd-enabled-scala-snapshot.yml b/tests/__snapshots__/xmlinputfactory-dtd-enabled-scala-snapshot.yml new file mode 100644 index 00000000..ed6503fc --- /dev/null +++ b/tests/__snapshots__/xmlinputfactory-dtd-enabled-scala-snapshot.yml @@ -0,0 +1,19 @@ +id: xmlinputfactory-dtd-enabled-scala +snapshots: + ? |- + val factory = XMLInputFactory.newFactory() + val fileReader = new FileReader(file) + : labels: + - source: XMLInputFactory.newFactory() + style: primary + start: 14 + end: 42 + ? |- + val factory = XMLInputFactory.newFactory() + val fileReader = new FileReader(file) + val fileReader = new FileReader(file) + : labels: + - source: XMLInputFactory.newFactory() + style: primary + start: 14 + end: 42 diff --git a/tests/c/libxml2-audit-parser-c-test.yml b/tests/c/libxml2-audit-parser-c-test.yml new file mode 100644 index 00000000..d5fca034 --- /dev/null +++ b/tests/c/libxml2-audit-parser-c-test.yml @@ -0,0 +1,8 @@ +id: libxml2-audit-parser-c +valid: + - | + xmlCtxtReadMemory(); +invalid: + - | + xmlParseInNodeContext(cur_node->parent, xml_filtered.c_str(), + (int)xml_filtered.length(), 0, &pNewNode); diff --git a/tests/c/sizeof-this-c-test.yml b/tests/c/sizeof-this-c-test.yml new file mode 100644 index 00000000..f9be53fb --- /dev/null +++ b/tests/c/sizeof-this-c-test.yml @@ -0,0 +1,7 @@ +id: sizeof-this-c +valid: + - | + return sizeof(*this); +invalid: + - | + return sizeof(this); diff --git a/tests/cpp/libxml2-audit-parser-cpp-test.yml b/tests/cpp/libxml2-audit-parser-cpp-test.yml new file mode 100644 index 00000000..f09ad2bd --- /dev/null +++ b/tests/cpp/libxml2-audit-parser-cpp-test.yml @@ -0,0 +1,8 @@ +id: libxml2-audit-parser-cpp +valid: + - | + xmlCtxtReadMemory(); +invalid: + - | + xmlParseInNodeContext(cur_node->parent, xml_filtered.c_str(), + (int)xml_filtered.length(), 0, &pNewNode); diff --git a/tests/csharp/httponly-false-csharp-test.yml b/tests/csharp/httponly-false-csharp-test.yml new file mode 100644 index 00000000..92062f04 --- /dev/null +++ b/tests/csharp/httponly-false-csharp-test.yml @@ -0,0 +1,11 @@ +id: httponly-false-csharp +valid: + - | + myHttpOnlyCookie.HttpOnly = true; + - | + options.Cookie.HttpOnly = true; +invalid: + - | + myHttpOnlyCookie.HttpOnly = false; + - | + options.Cookie.HttpOnly = false; diff --git a/tests/html/plaintext-http-link-html-test.yml b/tests/html/plaintext-http-link-html-test.yml new file mode 100644 index 00000000..c73d9bd0 --- /dev/null +++ b/tests/html/plaintext-http-link-html-test.yml @@ -0,0 +1,15 @@ +id: plaintext-http-link-html +valid: + - | + Astgrep + Astgrep + Astgrep +invalid: + - | + Astgrep + Astgrep + Astgrep + Astgrep + Astgrep + Astgrep + Astgrep diff --git a/tests/java/cbc-padding-oracle-java-test.yml b/tests/java/cbc-padding-oracle-java-test.yml new file mode 100644 index 00000000..8a0336cf --- /dev/null +++ b/tests/java/cbc-padding-oracle-java-test.yml @@ -0,0 +1,7 @@ +id: cbc-padding-oracle-java +valid: + - | + Cipher.getInstance("AES/GCM/NoPadding"); +invalid: + - | + Cipher.getInstance("AES/CBC/PKCS5Padding"); diff --git a/tests/java/cbc-padding-oracle-test.yml b/tests/java/cbc-padding-oracle-test.yml deleted file mode 100644 index 2085aa72..00000000 --- a/tests/java/cbc-padding-oracle-test.yml +++ /dev/null @@ -1,11 +0,0 @@ -id: cbc-padding-oracle -valid: - - | - Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); - c.init(Cipher.ENCRYPT_MODE, k, iv); - byte[] cipherText = c.doFinal(plainText); -invalid: - - | - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - IvParameterSpec iv = new IvParameterSpec(new byte[16]); - cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(new byte[16], "AES"), iv); \ No newline at end of file diff --git a/tests/java/cookie-secure-flag-false-java-test.yml b/tests/java/cookie-secure-flag-false-java-test.yml new file mode 100644 index 00000000..4d2b0fdb --- /dev/null +++ b/tests/java/cookie-secure-flag-false-java-test.yml @@ -0,0 +1,10 @@ +id: cookie-secure-flag-false-java +valid: + - | + response.addCookie(cookie); + cookie.setSecure(true); + cookie.setHttpOnly(true); + response.addCookie(cookie); +invalid: + - | + cookie.setSecure(false); diff --git a/tests/java/des-is-deprecated-java-test.yml b/tests/java/des-is-deprecated-java-test.yml new file mode 100644 index 00000000..bc26dbd7 --- /dev/null +++ b/tests/java/des-is-deprecated-java-test.yml @@ -0,0 +1,7 @@ +id: des-is-deprecated-java +valid: + - | + Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); +invalid: + - | + Cipher.getInstance("DES/ECB/PKCS5Padding"); diff --git a/tests/java/desede-is-deprecated-java-test.yml b/tests/java/desede-is-deprecated-java-test.yml new file mode 100644 index 00000000..7ae2996e --- /dev/null +++ b/tests/java/desede-is-deprecated-java-test.yml @@ -0,0 +1,8 @@ +id: desede-is-deprecated-java +valid: + - | + Cipher.getInstance("AES/GCM/NoPadding"); +invalid: + - | + Cipher.getInstance("DESede/ECB/PKCS5Padding"); + javax.crypto.KeyGenerator.getInstance("DES") diff --git a/tests/java/documentbuilderfactory-external-general-entities-true-java-test.yml b/tests/java/documentbuilderfactory-external-general-entities-true-java-test.yml new file mode 100644 index 00000000..a56a6eb5 --- /dev/null +++ b/tests/java/documentbuilderfactory-external-general-entities-true-java-test.yml @@ -0,0 +1,9 @@ +id: documentbuilderfactory-external-general-entities-true-java +valid: + - | + dbf.setFeature("http://xml.org/sax/features/external-general-entities" , false); + spf.setFeature("http://xml.org/sax/features/external-general-entities" , false); +invalid: + - | + dbf.setFeature("http://xml.org/sax/features/external-general-entities" , true); + spf.setFeature("http://xml.org/sax/features/external-general-entities" , true); diff --git a/tests/java/ecb-cipher-java-test.yml b/tests/java/ecb-cipher-java-test.yml new file mode 100644 index 00000000..b9089221 --- /dev/null +++ b/tests/java/ecb-cipher-java-test.yml @@ -0,0 +1,7 @@ +id: ecb-cipher-java +valid: + - | + Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); +invalid: + - | + Cipher c = Cipher.getInstance("AES/ECB/NoPadding"); diff --git a/tests/java/no-null-cipher-java-test.yml b/tests/java/no-null-cipher-java-test.yml new file mode 100644 index 00000000..ef38e9f6 --- /dev/null +++ b/tests/java/no-null-cipher-java-test.yml @@ -0,0 +1,8 @@ +id: no-null-cipher-java +valid: + - | + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); +invalid: + - | + Cipher doNothingCihper = new NullCipher(); + new javax.crypto.NullCipher(); diff --git a/tests/java/rsa-no-padding-java-test.yml b/tests/java/rsa-no-padding-java-test.yml new file mode 100644 index 00000000..cb962e9e --- /dev/null +++ b/tests/java/rsa-no-padding-java-test.yml @@ -0,0 +1,8 @@ +id: rsa-no-padding-java +valid: + - | + Cipher.getInstance("RSA/ECB/OAEPWithMD5AndMGF1Padding"); +invalid: + - | + Cipher.getInstance("RSA/None/NoPadding"); + Cipher.getInstance("RSA/NONE/NoPadding"); diff --git a/tests/java/system-setproperty-hardcoded-secret-java-test.yml b/tests/java/system-setproperty-hardcoded-secret-java-test.yml new file mode 100644 index 00000000..4bf72c91 --- /dev/null +++ b/tests/java/system-setproperty-hardcoded-secret-java-test.yml @@ -0,0 +1,9 @@ +id: system-setproperty-hardcoded-secret-java +valid: + - | + System.setProperty("javax.net.ssl.trustStorePassword", config); + System.setProperty("javax.net.ssl.keyStorePassword", config); +invalid: + - | + System.setProperty("javax.net.ssl.keyStorePassword", "password"); + System.setProperty("javax.net.ssl.trustStorePassword", "password"); diff --git a/tests/java/unencrypted-socket-java-test.yml b/tests/java/unencrypted-socket-java-test.yml new file mode 100644 index 00000000..d023debf --- /dev/null +++ b/tests/java/unencrypted-socket-java-test.yml @@ -0,0 +1,23 @@ +id: unencrypted-socket-java +valid: + - | + Socket soc = SSLSocketFactory.getDefault().createSocket("www.google.com", 443); + - | + ServerSocket ssoc = SSLServerSocketFactory.getDefault().createServerSocket(1234); +invalid: + - | + Socket soc = new Socket("www.google.com", 80); + - | + Socket soc1 = new Socket("www.google.com", 80, true); + - | + Socket soc2 = new Socket("www.google.com", 80, InetAddress.getByAddress(address), 13337); + - | + Socket soc3 = new Socket(InetAddress.getByAddress(remoteAddress), 80); + - | + ServerSocket ssoc = new ServerSocket(1234); + - | + ServerSocket ssoc1 = new ServerSocket(); + - | + ServerSocket ssoc2 = new ServerSocket(1234, 10); + - | + ServerSocket ssoc3 = new ServerSocket(1234, 10, InetAddress.getByAddress(address)); diff --git a/tests/java/use-of-aes-ecb-java-test.yml b/tests/java/use-of-aes-ecb-java-test.yml new file mode 100644 index 00000000..cd41ad9e --- /dev/null +++ b/tests/java/use-of-aes-ecb-java-test.yml @@ -0,0 +1,8 @@ +id: use-of-aes-ecb-java +valid: + - | + Cipher.getInstance("AES/CBC/PKCS7PADDING") +invalid: + - | + Cipher.getInstance("AES/ECB/NoPadding") + Cipher.getInstance("AES/ECB/PKCS5Padding") diff --git a/tests/java/use-of-blowfish-java-test.yml b/tests/java/use-of-blowfish-java-test.yml new file mode 100644 index 00000000..c4a43b2d --- /dev/null +++ b/tests/java/use-of-blowfish-java-test.yml @@ -0,0 +1,9 @@ +id: use-of-blowfish-java +valid: + - | + Cipher.getInstance("AES/CBC/PKCS7PADDING"); +invalid: + - | + Cipher.getInstance("Blowfish"); + - | + useCipher(Cipher.getInstance("Blowfish")); diff --git a/tests/java/use-of-md5-digest-utils-java-test.yml b/tests/java/use-of-md5-digest-utils-java-test.yml new file mode 100644 index 00000000..f6bc228d --- /dev/null +++ b/tests/java/use-of-md5-digest-utils-java-test.yml @@ -0,0 +1,9 @@ +id: use-of-md5-digest-utils-java +valid: + - | + MessageDigest md5Digest = MessageDigest.getInstance("MD5"); + - | + byte[] hashValue = DigestUtils.getSha512Digest().digest(password.getBytes()); +invalid: + - | + byte[] hashValue = DigestUtils.getMd5Digest().digest(password.getBytes()); diff --git a/tests/java/use-of-md5-java-test.yml b/tests/java/use-of-md5-java-test.yml new file mode 100644 index 00000000..af34098d --- /dev/null +++ b/tests/java/use-of-md5-java-test.yml @@ -0,0 +1,7 @@ +id: use-of-md5-java +valid: + - | + MessageDigest md5Digest = MessageDigest.getInstance("SHA-512"); +invalid: + - | + MessageDigest md5Digest = MessageDigest.getInstance("MD5"); diff --git a/tests/java/use-of-rc2-java-test.yml b/tests/java/use-of-rc2-java-test.yml new file mode 100644 index 00000000..74f8d6d3 --- /dev/null +++ b/tests/java/use-of-rc2-java-test.yml @@ -0,0 +1,8 @@ +id: use-of-rc2-java +valid: + - | + Cipher.getInstance("AES/CBC/PKCS7PADDING"); +invalid: + - | + useCipher(Cipher.getInstance("RC2")); + Cipher.getInstance("RC2"); diff --git a/tests/java/use-of-rc4-java-test.yml b/tests/java/use-of-rc4-java-test.yml new file mode 100644 index 00000000..a82db3b3 --- /dev/null +++ b/tests/java/use-of-rc4-java-test.yml @@ -0,0 +1,9 @@ +id: use-of-rc4-java +valid: + - | + Cipher.getInstance("AES/CBC/PKCS7PADDING"); +invalid: + - | + Cipher.getInstance("RC4"); + - | + useCipher(Cipher.getInstance("RC4")); diff --git a/tests/java/use-of-sha1-java-test.yml b/tests/java/use-of-sha1-java-test.yml new file mode 100644 index 00000000..307dc641 --- /dev/null +++ b/tests/java/use-of-sha1-java-test.yml @@ -0,0 +1,10 @@ +id: use-of-sha1-java +valid: + - | + java.io.File fileTarget = new java.io.File( + new java.io.File(org.owasp.benchmark.helpers.Utils.TESTFILES_DIR), + "passwordFile.txt"); +invalid: + - | + java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA1", "SUN"); + DigestUtils.getSha1Digest().digest(password.getBytes()); diff --git a/tests/java/use-of-weak-rsa-key-java-test.yml b/tests/java/use-of-weak-rsa-key-java-test.yml new file mode 100644 index 00000000..c1aee8fa --- /dev/null +++ b/tests/java/use-of-weak-rsa-key-java-test.yml @@ -0,0 +1,18 @@ +id: use-of-weak-rsa-key-java +valid: + - | + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(2048); +invalid: + - | + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(512); + - | + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(-512); + - | + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(512.09); + - | + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(512.0); diff --git a/tests/java/weak-ssl-context-java-test.yml b/tests/java/weak-ssl-context-java-test.yml new file mode 100644 index 00000000..66505656 --- /dev/null +++ b/tests/java/weak-ssl-context-java-test.yml @@ -0,0 +1,19 @@ +id: weak-ssl-context-java +valid: + - | + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); + - | + SSLContext ctx = SSLContext.getInstance("TLSv1.3"); + - | + SSLContext ctx = SSLContext.getInstance(getSslContext()); +invalid: + - | + SSLContext ctx = SSLContext.getInstance("SSL"); + - | + SSLContext ctx = SSLContext.getInstance("TLS"); + - | + SSLContext ctx = SSLContext.getInstance("TLSv1"); + - | + SSLContext ctx = SSLContext.getInstance("SSLv3"); + - | + SSLContext ctx = SSLContext.getInstance("TLSv1.1"); diff --git a/tests/kotlin/des-is-deprecated-kotlin-test.yml b/tests/kotlin/des-is-deprecated-kotlin-test.yml new file mode 100644 index 00000000..60949d48 --- /dev/null +++ b/tests/kotlin/des-is-deprecated-kotlin-test.yml @@ -0,0 +1,7 @@ +id: des-is-deprecated-kotlin +valid: + - | + Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); +invalid: + - | + Cipher.getInstance("DES/ECB/PKCS5Padding"); diff --git a/tests/kotlin/desede-is-deprecated-kotlin-test.yml b/tests/kotlin/desede-is-deprecated-kotlin-test.yml new file mode 100644 index 00000000..c3d2e28e --- /dev/null +++ b/tests/kotlin/desede-is-deprecated-kotlin-test.yml @@ -0,0 +1,8 @@ +id: desede-is-deprecated-kotlin +valid: + - | + Cipher.getInstance("AES/GCM/NoPadding"); +invalid: + - | + Cipher.getInstance("DESede/ECB/PKCS5Padding"); + javax.crypto.KeyGenerator.getInstance("DES") diff --git a/tests/kotlin/rsa-no-padding-kotlin.yml b/tests/kotlin/rsa-no-padding-kotlin.yml new file mode 100644 index 00000000..6dc46d21 --- /dev/null +++ b/tests/kotlin/rsa-no-padding-kotlin.yml @@ -0,0 +1,8 @@ +id: rsa-no-padding-kotlin +valid: + - | + Cipher.getInstance("RSA/ECB/OAEPWithMD5AndMGF1Padding"); +invalid: + - | + Cipher.getInstance("RSA/None/NoPadding"); + Cipher.getInstance("RSA/NONE/NoPadding"); diff --git a/tests/kotlin/system-setproperty-hardcoded-secret-kotlin-test.yml b/tests/kotlin/system-setproperty-hardcoded-secret-kotlin-test.yml new file mode 100644 index 00000000..d66da67a --- /dev/null +++ b/tests/kotlin/system-setproperty-hardcoded-secret-kotlin-test.yml @@ -0,0 +1,9 @@ +id: system-setproperty-hardcoded-secret-kotlin +valid: + - | + System.setProperty("javax.net.ssl.trustStorePassword", config); + System.setProperty("javax.net.ssl.keyStorePassword", config); +invalid: + - | + System.setProperty("javax.net.ssl.keyStorePassword", "password"); + System.setProperty("javax.net.ssl.trustStorePassword", "password"); diff --git a/tests/kotlin/use-of-weak-rsa-key-kotlin-test.yml b/tests/kotlin/use-of-weak-rsa-key-kotlin-test.yml new file mode 100644 index 00000000..199c4b1e --- /dev/null +++ b/tests/kotlin/use-of-weak-rsa-key-kotlin-test.yml @@ -0,0 +1,9 @@ +id: use-of-weak-rsa-key-kotlin +valid: + - | + KeyPairGenerator.getInstance("RSA") + keyGen.initialize(2048); +invalid: + - | + KeyPairGenerator.getInstance("RSA") + keyGen.initialize(-5.12); diff --git a/tests/rust/reqwest-accept-invalid-rust-test.yml b/tests/rust/reqwest-accept-invalid-rust-test.yml new file mode 100644 index 00000000..894c5cec --- /dev/null +++ b/tests/rust/reqwest-accept-invalid-rust-test.yml @@ -0,0 +1,13 @@ +id: reqwest-accept-invalid-rust +valid: + - | + reqwest::Client::builder().user_agent("USER AGENT") +invalid: + - | + reqwest::Client::builder().danger_accept_invalid_hostnames(true) + - | + reqwest::Client::builder().danger_accept_invalid_certs(true) + - | + reqwest::Client::builder().user_agent("USER AGENT").cookie_store(true).danger_accept_invalid_hostnames(true) + - | + reqwest::Client::builder().user_agent("USER AGENT").cookie_store(true).danger_accept_invalid_certs(true) diff --git a/tests/scala/rsa-padding-set-scala-test.yml b/tests/scala/rsa-padding-set-scala-test.yml new file mode 100644 index 00000000..3196e148 --- /dev/null +++ b/tests/scala/rsa-padding-set-scala-test.yml @@ -0,0 +1,9 @@ +id: rsa-padding-set-scala +valid: + - | + Cipher.getInstance("AES/CBC/PKCS5Padding"); + Cipher.getInstance("DES/ECB/PKCS5Padding"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); +invalid: + - | + Cipher.getInstance("RSA/ECB/NoPadding") diff --git a/tests/scala/xmlinputfactory-dtd-enabled-scala-test.yml b/tests/scala/xmlinputfactory-dtd-enabled-scala-test.yml new file mode 100644 index 00000000..ab78f6be --- /dev/null +++ b/tests/scala/xmlinputfactory-dtd-enabled-scala-test.yml @@ -0,0 +1,11 @@ +id: xmlinputfactory-dtd-enabled-scala +valid: + - | + val factory = XMLInputFactory.newInstance + factory.setProperty("javax.xml.stream.isSupportingExternalEntities", false) + val fileReader = new FileReader(file) +invalid: + - | + val factory = XMLInputFactory.newFactory() + val fileReader = new FileReader(file) + val fileReader = new FileReader(file) \ No newline at end of file diff --git a/tests/swift/insecure-biometrics-swift-test.yml b/tests/swift/insecure-biometrics-swift-test.yml new file mode 100644 index 00000000..fffee11c --- /dev/null +++ b/tests/swift/insecure-biometrics-swift-test.yml @@ -0,0 +1,7 @@ +id: insecure-biometrics-swift +valid: + - | + context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) +invalid: + - | + context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "Authenticate to the application" From 640eba457267ecc0c1c6fb8f9b2060b6c9fa03f7 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Tue, 17 Sep 2024 17:41:08 +0530 Subject: [PATCH 02/41] Made changes to scala rule --- rules/scala/security/xmlinputfactory-dtd-enabled-scala.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rules/scala/security/xmlinputfactory-dtd-enabled-scala.yml b/rules/scala/security/xmlinputfactory-dtd-enabled-scala.yml index 9ba9cb7f..732fddc9 100644 --- a/rules/scala/security/xmlinputfactory-dtd-enabled-scala.yml +++ b/rules/scala/security/xmlinputfactory-dtd-enabled-scala.yml @@ -19,7 +19,4 @@ rule: - pattern: new XMLInputFactory($$$) precedes: not: - pattern: $XMLFACTORY.setProperty($MODE, false) -constraints: - MODE: - regex: "javax.xml.stream.isSupportingExternalEntities" + pattern: $XMLFACTORY.setProperty(javax.xml.stream.isSupportingExternalEntities, false) From 57c1c8385e3ca0bdc94170c389ce0b7ff7be30b7 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 19 Sep 2024 17:12:37 +0530 Subject: [PATCH 03/41] python-cassandra-empty-password --- ...python-cassandra-empty-password-python.yml | 49 +++++++++++++++++++ ...thon-cassandra-empty-password-snapshot.yml | 38 ++++++++++++++ ...n-cassandra-empty-password-python-test.yml | 12 +++++ 3 files changed, 99 insertions(+) create mode 100644 rules/python/security/python-cassandra-empty-password-python.yml create mode 100644 tests/__snapshots__/python-cassandra-empty-password-snapshot.yml create mode 100644 tests/python/python-cassandra-empty-password-python-test.yml diff --git a/rules/python/security/python-cassandra-empty-password-python.yml b/rules/python/security/python-cassandra-empty-password-python.yml new file mode 100644 index 00000000..33516853 --- /dev/null +++ b/rules/python/security/python-cassandra-empty-password-python.yml @@ -0,0 +1,49 @@ +id: python-cassandra-empty-password +language: python +severity: warning +message: >- + The application creates a database connection with an empty password. + This can lead to unauthorized access by either an internal or external + malicious actor. To prevent this vulnerability, enforce authentication + when connecting to a database by using environment variables to securely + provide credentials or retrieving them from a secure vault or HSM + (Hardware Security Module). +note: >- + [CWE-287]: Improper Authentication + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + +utils: + from_imported_module: + any: + - pattern: PlainTextAuthProvider($USER, $QUOTES) + - pattern: PlainTextAuthProvider($USER, $QUOTES, $$$) + - pattern: PlainTextAuthProvider($$$, password=$QUOTES) + - pattern: PlainTextAuthProvider($$$, password=$QUOTES, $$$) + - pattern: SaslAuthProvider($$$, password=$QUOTES) + - pattern: SaslAuthProvider($$$, password=$QUOTES, $$$) + - pattern: PlainTextAuthProvider(username='user', password='') + + inside_module_with_import_statement: + inside: + stopBy: end + kind: module + has: + kind: import_from_statement + pattern: from cassandra.auth import PlainTextAuthProvider + +rule: + any: + - pattern: cassandra.auth.PlainTextAuthProvider($USER, $QUOTES) + - pattern: cassandra.auth.PlainTextAuthProvider($USER, $QUOTES, $$$) + - pattern: cassandra.auth.PlainTextAuthProvider($$$, password=$QUOTES) + - pattern: cassandra.auth.PlainTextAuthProvider($$$, password=$QUOTES, $$$) + - pattern: cassandra.auth.SaslAuthProvider($$$, password=$QUOTES) + - pattern: cassandra.auth.SaslAuthProvider($$$, password=$QUOTES, $$$) + - all: + - matches: from_imported_module + - matches: inside_module_with_import_statement + +constraints: + QUOTES: + regex: (''|""|``) diff --git a/tests/__snapshots__/python-cassandra-empty-password-snapshot.yml b/tests/__snapshots__/python-cassandra-empty-password-snapshot.yml new file mode 100644 index 00000000..7ec526a6 --- /dev/null +++ b/tests/__snapshots__/python-cassandra-empty-password-snapshot.yml @@ -0,0 +1,38 @@ +id: python-cassandra-empty-password +snapshots: + ? | + from cassandra.auth import PlainTextAuthProvider + auth_provider = PlainTextAuthProvider('user', '') + : labels: + - source: PlainTextAuthProvider('user', '') + style: primary + start: 65 + end: 98 + - source: from cassandra.auth import PlainTextAuthProvider + style: secondary + start: 0 + end: 48 + - source: | + from cassandra.auth import PlainTextAuthProvider + auth_provider = PlainTextAuthProvider('user', '') + style: secondary + start: 0 + end: 99 + ? | + from cassandra.auth import PlainTextAuthProvider + auth_provider = PlainTextAuthProvider(username='user', password='') + : labels: + - source: PlainTextAuthProvider(username='user', password='') + style: primary + start: 65 + end: 116 + - source: from cassandra.auth import PlainTextAuthProvider + style: secondary + start: 0 + end: 48 + - source: | + from cassandra.auth import PlainTextAuthProvider + auth_provider = PlainTextAuthProvider(username='user', password='') + style: secondary + start: 0 + end: 117 diff --git a/tests/python/python-cassandra-empty-password-python-test.yml b/tests/python/python-cassandra-empty-password-python-test.yml new file mode 100644 index 00000000..f8957686 --- /dev/null +++ b/tests/python/python-cassandra-empty-password-python-test.yml @@ -0,0 +1,12 @@ +id: python-cassandra-empty-password +valid: + - | + from cassandra.auth import PlainTextAuthProvider + auth_provider = PlainTextAuthProvider('user', 'pass') +invalid: + - | + from cassandra.auth import PlainTextAuthProvider + auth_provider = PlainTextAuthProvider('user', '') + - | + from cassandra.auth import PlainTextAuthProvider + auth_provider = PlainTextAuthProvider(username='user', password='') From 3c917d091160f22421005fa8af72833302707c33 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 19 Sep 2024 17:21:02 +0530 Subject: [PATCH 04/41] python-cassandra-empty-password-python rule id changed --- .../python/security/python-cassandra-empty-password-python.yml | 2 +- ....yml => python-cassandra-empty-password-python-snapshot.yml} | 2 +- tests/python/python-cassandra-empty-password-python-test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename tests/__snapshots__/{python-cassandra-empty-password-snapshot.yml => python-cassandra-empty-password-python-snapshot.yml} (96%) diff --git a/rules/python/security/python-cassandra-empty-password-python.yml b/rules/python/security/python-cassandra-empty-password-python.yml index 33516853..d4cd10b2 100644 --- a/rules/python/security/python-cassandra-empty-password-python.yml +++ b/rules/python/security/python-cassandra-empty-password-python.yml @@ -1,4 +1,4 @@ -id: python-cassandra-empty-password +id: python-cassandra-empty-password-python language: python severity: warning message: >- diff --git a/tests/__snapshots__/python-cassandra-empty-password-snapshot.yml b/tests/__snapshots__/python-cassandra-empty-password-python-snapshot.yml similarity index 96% rename from tests/__snapshots__/python-cassandra-empty-password-snapshot.yml rename to tests/__snapshots__/python-cassandra-empty-password-python-snapshot.yml index 7ec526a6..0183313c 100644 --- a/tests/__snapshots__/python-cassandra-empty-password-snapshot.yml +++ b/tests/__snapshots__/python-cassandra-empty-password-python-snapshot.yml @@ -1,4 +1,4 @@ -id: python-cassandra-empty-password +id: python-cassandra-empty-password-python snapshots: ? | from cassandra.auth import PlainTextAuthProvider diff --git a/tests/python/python-cassandra-empty-password-python-test.yml b/tests/python/python-cassandra-empty-password-python-test.yml index f8957686..885b0dac 100644 --- a/tests/python/python-cassandra-empty-password-python-test.yml +++ b/tests/python/python-cassandra-empty-password-python-test.yml @@ -1,4 +1,4 @@ -id: python-cassandra-empty-password +id: python-cassandra-empty-password-python valid: - | from cassandra.auth import PlainTextAuthProvider From 7ae95c52d6323bc4ca05193985126c7921dfca8a Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 19 Sep 2024 17:39:43 +0530 Subject: [PATCH 05/41] changed rule of python-cassandra-empty-password-python --- .../python-cassandra-empty-password-python.yml | 6 ++++-- ...thon-cassandra-empty-password-python-snapshot.yml | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/rules/python/security/python-cassandra-empty-password-python.yml b/rules/python/security/python-cassandra-empty-password-python.yml index d4cd10b2..060ce96d 100644 --- a/rules/python/security/python-cassandra-empty-password-python.yml +++ b/rules/python/security/python-cassandra-empty-password-python.yml @@ -40,9 +40,11 @@ rule: - pattern: cassandra.auth.PlainTextAuthProvider($$$, password=$QUOTES, $$$) - pattern: cassandra.auth.SaslAuthProvider($$$, password=$QUOTES) - pattern: cassandra.auth.SaslAuthProvider($$$, password=$QUOTES, $$$) - - all: + - any: - matches: from_imported_module - - matches: inside_module_with_import_statement + follows: + stopBy: end + matches: inside_module_with_import_statement constraints: QUOTES: diff --git a/tests/__snapshots__/python-cassandra-empty-password-python-snapshot.yml b/tests/__snapshots__/python-cassandra-empty-password-python-snapshot.yml index 0183313c..e07435de 100644 --- a/tests/__snapshots__/python-cassandra-empty-password-python-snapshot.yml +++ b/tests/__snapshots__/python-cassandra-empty-password-python-snapshot.yml @@ -18,6 +18,12 @@ snapshots: style: secondary start: 0 end: 99 + - source: | + from cassandra.auth import PlainTextAuthProvider + auth_provider = PlainTextAuthProvider('user', '') + style: secondary + start: 0 + end: 99 ? | from cassandra.auth import PlainTextAuthProvider auth_provider = PlainTextAuthProvider(username='user', password='') @@ -36,3 +42,9 @@ snapshots: style: secondary start: 0 end: 117 + - source: | + from cassandra.auth import PlainTextAuthProvider + auth_provider = PlainTextAuthProvider(username='user', password='') + style: secondary + start: 0 + end: 117 From 55368780c60747aa83287b96ceac27f00eede036 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 19 Sep 2024 17:47:55 +0530 Subject: [PATCH 06/41] hashids-with-django-secret-python --- .../hashids-with-django-secret-python.yml | 18 ++++++++++++++++++ ...hids-with-django-secret-python-snapshot.yml | 11 +++++++++++ .../hashids-with-django-secret-python-test.yml | 9 +++++++++ 3 files changed, 38 insertions(+) create mode 100644 rules/python/security/hashids-with-django-secret-python.yml create mode 100644 tests/__snapshots__/hashids-with-django-secret-python-snapshot.yml create mode 100644 tests/python/hashids-with-django-secret-python-test.yml diff --git a/rules/python/security/hashids-with-django-secret-python.yml b/rules/python/security/hashids-with-django-secret-python.yml new file mode 100644 index 00000000..d861b038 --- /dev/null +++ b/rules/python/security/hashids-with-django-secret-python.yml @@ -0,0 +1,18 @@ +id: hashids-with-django-secret-python +language: python +severity: warning +message: >- + The Django secret key is used as salt in HashIDs. The HashID mechanism + is not secure. By observing sufficient HashIDs, the salt used to construct + them can be recovered. This means the Django secret key can be obtained by + attackers, through the HashIDs. +note: >- + [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm + [OWASP A02:2021]: Cryptographic Failures + [REFERENCES] + https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-SECRET_KEY + http://carnage.github.io/2015/08/cryptanalysis-of-hashids +rule: + any: + - pattern: Hashids(salt=settings.SECRET_KEY, $$$) + - pattern: Hashids(settings.SECRET_KEY, $$$) diff --git a/tests/__snapshots__/hashids-with-django-secret-python-snapshot.yml b/tests/__snapshots__/hashids-with-django-secret-python-snapshot.yml new file mode 100644 index 00000000..da2eddb5 --- /dev/null +++ b/tests/__snapshots__/hashids-with-django-secret-python-snapshot.yml @@ -0,0 +1,11 @@ +id: hashids-with-django-secret-python +snapshots: + ? | + Hashids(salt=settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH) + Hashids(salt=settings.SECRET_KEY, min_length=4, alphabet="abcdefghijklmnopqrstuvwxyz") + Hashids(settings.SECRET_KEY, min_length=length, alphabet=alphabet) + : labels: + - source: Hashids(salt=settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH) + style: primary + start: 0 + end: 73 diff --git a/tests/python/hashids-with-django-secret-python-test.yml b/tests/python/hashids-with-django-secret-python-test.yml new file mode 100644 index 00000000..03eb2fce --- /dev/null +++ b/tests/python/hashids-with-django-secret-python-test.yml @@ -0,0 +1,9 @@ +id: hashids-with-django-secret-python +valid: + - | + Hashids(salt=md5.hexdigest(), min_length=16) +invalid: + - | + Hashids(salt=settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH) + Hashids(salt=settings.SECRET_KEY, min_length=4, alphabet="abcdefghijklmnopqrstuvwxyz") + Hashids(settings.SECRET_KEY, min_length=length, alphabet=alphabet) From 1c372cd45d947d70efbf6262aca0e35ee8846246 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 19 Sep 2024 17:49:12 +0530 Subject: [PATCH 07/41] documentbuilderfactory-external-parameter-entities-true-java --- ...actory-external-parameter-entities-true-java.yml | 13 +++++++++++++ ...ternal-parameter-entities-true-java-snapshot.yml | 10 ++++++++++ ...y-external-parameter-entities-true-java-test.yml | 8 ++++++++ 3 files changed, 31 insertions(+) create mode 100644 rules/java/security/documentbuilderfactory-external-parameter-entities-true-java.yml create mode 100644 tests/__snapshots__/documentbuilderfactory-external-parameter-entities-true-java-snapshot.yml create mode 100644 tests/java/documentbuilderfactory-external-parameter-entities-true-java-test.yml diff --git a/rules/java/security/documentbuilderfactory-external-parameter-entities-true-java.yml b/rules/java/security/documentbuilderfactory-external-parameter-entities-true-java.yml new file mode 100644 index 00000000..7dcccba7 --- /dev/null +++ b/rules/java/security/documentbuilderfactory-external-parameter-entities-true-java.yml @@ -0,0 +1,13 @@ +id: documentbuilderfactory-external-parameter-entities-true-java +severity: warning +language: java +message: >- + External entities are allowed for $DBFACTORY. This is vulnerable to XML + external entity attacks. Disable this by setting the feature + "http://xml.org/sax/features/external-parameter-entities" to false. +note: >- + [CWE-611] Improper Restriction of XML External Entity Reference. + [REFERENCES] + - https://blog.sonarsource.com/secure-xml-processor +rule: + pattern: $DBFACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities",true); diff --git a/tests/__snapshots__/documentbuilderfactory-external-parameter-entities-true-java-snapshot.yml b/tests/__snapshots__/documentbuilderfactory-external-parameter-entities-true-java-snapshot.yml new file mode 100644 index 00000000..c10c8249 --- /dev/null +++ b/tests/__snapshots__/documentbuilderfactory-external-parameter-entities-true-java-snapshot.yml @@ -0,0 +1,10 @@ +id: documentbuilderfactory-external-parameter-entities-true-java +snapshots: + ? | + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities" , true); + spf.setFeature("http://xml.org/sax/features/external-parameter-entities" , true); + : labels: + - source: dbf.setFeature("http://xml.org/sax/features/external-parameter-entities" , true); + style: primary + start: 0 + end: 81 diff --git a/tests/java/documentbuilderfactory-external-parameter-entities-true-java-test.yml b/tests/java/documentbuilderfactory-external-parameter-entities-true-java-test.yml new file mode 100644 index 00000000..309b83da --- /dev/null +++ b/tests/java/documentbuilderfactory-external-parameter-entities-true-java-test.yml @@ -0,0 +1,8 @@ +id: documentbuilderfactory-external-parameter-entities-true-java +valid: + - | + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities" , false); +invalid: + - | + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities" , true); + spf.setFeature("http://xml.org/sax/features/external-parameter-entities" , true); From 50919dcb43891da915044f04164115afe1148ff7 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 20 Sep 2024 18:44:24 +0530 Subject: [PATCH 08/41] python-elasticsearch-hardcoded-bearer-auth-python --- ...ticsearch-hardcoded-bearer-auth-python.yml | 29 +++++++++++++++++++ ...-hardcoded-bearer-auth-python-snapshot.yml | 11 +++++++ ...arch-hardcoded-bearer-auth-python-test.yml | 9 ++++++ 3 files changed, 49 insertions(+) create mode 100644 rules/python/security/python-elasticsearch-hardcoded-bearer-auth-python.yml create mode 100644 tests/__snapshots__/python-elasticsearch-hardcoded-bearer-auth-python-snapshot.yml create mode 100644 tests/python/python-elasticsearch-hardcoded-bearer-auth-python-test.yml diff --git a/rules/python/security/python-elasticsearch-hardcoded-bearer-auth-python.yml b/rules/python/security/python-elasticsearch-hardcoded-bearer-auth-python.yml new file mode 100644 index 00000000..9c5bc077 --- /dev/null +++ b/rules/python/security/python-elasticsearch-hardcoded-bearer-auth-python.yml @@ -0,0 +1,29 @@ +id: python-elasticsearch-hardcoded-bearer-auth-python +severity: warning +language: python +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. Use + environment variables to securely provide credentials and other secrets or + retrieve them from a secure vault or Hardware Security Module (HSM). +note: >- + [CWE-798] Use of Hard-coded Credentials. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +rule: + any: + - pattern: Elasticsearch($$$, bearer_auth="$$$",$$$) + - pattern: Elasticsearch($$$,bearer_auth=$$$) + - pattern: $ES.options(bearer_auth="$$$").$$$ + not: + follows: + pattern: elasticsearch.Elasticsearch($$$) + - pattern: $ES.options($$$,bearer_auth="$$$").$$$ + not: + follows: + pattern: elasticsearch.Elasticsearch($$$) + - pattern: $ES.options($$$,bearer_auth="$$$",$$$) + not: + follows: + pattern: elasticsearch.Elasticsearch($$$) diff --git a/tests/__snapshots__/python-elasticsearch-hardcoded-bearer-auth-python-snapshot.yml b/tests/__snapshots__/python-elasticsearch-hardcoded-bearer-auth-python-snapshot.yml new file mode 100644 index 00000000..37456744 --- /dev/null +++ b/tests/__snapshots__/python-elasticsearch-hardcoded-bearer-auth-python-snapshot.yml @@ -0,0 +1,11 @@ +id: python-elasticsearch-hardcoded-bearer-auth-python +snapshots: + ? | + es.options(bearer_auth="password").indices. + es = Elasticsearch("https://localhost:9200",bearer_auth=pswd) + es = Elasticsearch("https://localhost:9200",bearer_auth="token-value") + : labels: + - source: es.options(bearer_auth="password").indices + style: primary + start: 0 + end: 42 diff --git a/tests/python/python-elasticsearch-hardcoded-bearer-auth-python-test.yml b/tests/python/python-elasticsearch-hardcoded-bearer-auth-python-test.yml new file mode 100644 index 00000000..1d1e266a --- /dev/null +++ b/tests/python/python-elasticsearch-hardcoded-bearer-auth-python-test.yml @@ -0,0 +1,9 @@ +id: python-elasticsearch-hardcoded-bearer-auth-python +valid: + - | + +invalid: + - | + es.options(bearer_auth="password").indices. + es = Elasticsearch("https://localhost:9200",bearer_auth=pswd) + es = Elasticsearch("https://localhost:9200",bearer_auth="token-value") From d3b8e8f3db8918f5205dbc67aa06ef9c5492f83d Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Mon, 23 Sep 2024 17:44:28 +0530 Subject: [PATCH 09/41] documentbuilderfactory-disallow-doctype-decl-false-java --- ...ctory-disallow-doctype-decl-false-java.yml | 29 +++++++++ ...allow-doctype-decl-false-java-snapshot.yml | 36 +++++++++++ ...-disallow-doctype-decl-false-java-test.yml | 63 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 rules/java/security/documentbuilderfactory-disallow-doctype-decl-false-java.yml create mode 100644 tests/__snapshots__/documentbuilderfactory-disallow-doctype-decl-false-java-snapshot.yml create mode 100644 tests/java/documentbuilderfactory-disallow-doctype-decl-false-java-test.yml diff --git a/rules/java/security/documentbuilderfactory-disallow-doctype-decl-false-java.yml b/rules/java/security/documentbuilderfactory-disallow-doctype-decl-false-java.yml new file mode 100644 index 00000000..345a3663 --- /dev/null +++ b/rules/java/security/documentbuilderfactory-disallow-doctype-decl-false-java.yml @@ -0,0 +1,29 @@ +id: documentbuilderfactory-disallow-doctype-decl-false-java +language: java +severity: warning +message: >- + DOCTYPE declarations are enabled for $DBFACTORY. Without prohibiting + external entity declarations, this is vulnerable to XML external entity + attacks. Disable this by setting the feature + "http://apache.org/xml/features/disallow-doctype-decl" to true. + Alternatively, allow DOCTYPE declarations and only prohibit external + entities declarations. This can be done by setting the features + "http://xml.org/sax/features/external-general-entities" and + "http://xml.org/sax/features/external-parameter-entities" to false. +note: >- + [CWE-611]: mproper Restriction of XML External Entity Reference + [OWASP A04:2017]: XML External Entities (XXE) + [OWASP A05:2021 - Security Misconfiguration] + [REFERENCES] + https://blog.sonarsource.com/secure-xml-processor + https://xerces.apache.org/xerces2-j/features.html +rule: + any: + - pattern: $D.setFeature("http://apache.org/xml/features/disallow-doctype-decl",false); + follows: + pattern: DocumentBuilderFactory $D = $_; + stopBy: end + - pattern: $S.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + follows: + pattern: SAXParserFactory $S = $_; + stopBy: end diff --git a/tests/__snapshots__/documentbuilderfactory-disallow-doctype-decl-false-java-snapshot.yml b/tests/__snapshots__/documentbuilderfactory-disallow-doctype-decl-false-java-snapshot.yml new file mode 100644 index 00000000..ae72bb04 --- /dev/null +++ b/tests/__snapshots__/documentbuilderfactory-disallow-doctype-decl-false-java-snapshot.yml @@ -0,0 +1,36 @@ +id: documentbuilderfactory-disallow-doctype-decl-false-java +snapshots: + ? | + ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + //ruleid:documentbuilderfactory-disallow-doctype-decl-false + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + //fix:documentbuilderfactory-disallow-doctype-decl-false + //dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + } + : labels: + - source: dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + style: primary + start: 170 + end: 248 + - source: DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + style: secondary + start: 35 + end: 101 + ? | + ParserConfigurationException { + SAXParserFactory spf = SAXParserFactory.newInstance(); + //ruleid:documentbuilderfactory-disallow-doctype-decl-false + spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + //fix:documentbuilderfactory-disallow-doctype-decl-false + //spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + } + : labels: + - source: spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + style: primary + start: 158 + end: 236 + - source: SAXParserFactory spf = SAXParserFactory.newInstance(); + style: secondary + start: 35 + end: 89 diff --git a/tests/java/documentbuilderfactory-disallow-doctype-decl-false-java-test.yml b/tests/java/documentbuilderfactory-disallow-doctype-decl-false-java-test.yml new file mode 100644 index 00000000..51cb4f21 --- /dev/null +++ b/tests/java/documentbuilderfactory-disallow-doctype-decl-false-java-test.yml @@ -0,0 +1,63 @@ +id: documentbuilderfactory-disallow-doctype-decl-false-java +valid: + - | + ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + //ok:documentbuilderfactory-disallow-doctype-decl-false + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + } + - | + ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + //ok:documentbuilderfactory-disallow-doctype-decl-false + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + } + - | + ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + //ok:documentbuilderfactory-disallow-doctype-decl-false + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); + } + - | + ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + //ok:documentbuilderfactory-disallow-doctype-decl-false + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + } + - | + ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + //ok:documentbuilderfactory-disallow-doctype-decl-false + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + } + - | + ParserConfigurationException { + SAXParserFactory spf = SAXParserFactory.newInstance(); + //ok:documentbuilderfactory-disallow-doctype-decl-false + spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + } +invalid: + - | + ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + //ruleid:documentbuilderfactory-disallow-doctype-decl-false + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + //fix:documentbuilderfactory-disallow-doctype-decl-false + //dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + } + - | + ParserConfigurationException { + SAXParserFactory spf = SAXParserFactory.newInstance(); + //ruleid:documentbuilderfactory-disallow-doctype-decl-false + spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + //fix:documentbuilderfactory-disallow-doctype-decl-false + //spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + } From 1b510d2483421b05a78fa6f5ae99ad2a210c2c89 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Mon, 23 Sep 2024 17:45:29 +0530 Subject: [PATCH 10/41] Valid test case added to python-elasticsearch-hardcoded-bearer-auth-python --- .../python-elasticsearch-hardcoded-bearer-auth-python-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/python/python-elasticsearch-hardcoded-bearer-auth-python-test.yml b/tests/python/python-elasticsearch-hardcoded-bearer-auth-python-test.yml index 1d1e266a..f71c8562 100644 --- a/tests/python/python-elasticsearch-hardcoded-bearer-auth-python-test.yml +++ b/tests/python/python-elasticsearch-hardcoded-bearer-auth-python-test.yml @@ -1,6 +1,7 @@ id: python-elasticsearch-hardcoded-bearer-auth-python valid: - | + es = Elasticsearch("https://localhost:9200"); invalid: - | From 88eb5a4f5642460e039619294411cdd8c7f9b2d7 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Mon, 23 Sep 2024 17:46:30 +0530 Subject: [PATCH 11/41] gcm-nonce-reuse-java --- rules/java/security/gcm-nonce-reuse-java.yml | 16 ++++++++++++++++ .../gcm-nonce-reuse-java-snapshot.yml | 14 ++++++++++++++ tests/java/gcm-nonce-reuse-java-test.yml | 9 +++++++++ 3 files changed, 39 insertions(+) create mode 100644 rules/java/security/gcm-nonce-reuse-java.yml create mode 100644 tests/__snapshots__/gcm-nonce-reuse-java-snapshot.yml create mode 100644 tests/java/gcm-nonce-reuse-java-test.yml diff --git a/rules/java/security/gcm-nonce-reuse-java.yml b/rules/java/security/gcm-nonce-reuse-java.yml new file mode 100644 index 00000000..a6cc2749 --- /dev/null +++ b/rules/java/security/gcm-nonce-reuse-java.yml @@ -0,0 +1,16 @@ +id: gcm-nonce-reuse-java +language: java +severity: warning +message: >- + GCM IV/nonce is reused: encryption can be totally useless. +note: >- + [CWE-323] Reusing a Nonce, Key Pair in Encryption. + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + any: + - pattern: GCMParameterSpec $$$ = new GCMParameterSpec(GCM_TAG_LENGTH * 8, $A); + follows: + pattern: byte[] $A = $_; + stopBy: end + - pattern: new GCMParameterSpec($$$, "$$$".getBytes($$$), $$$) diff --git a/tests/__snapshots__/gcm-nonce-reuse-java-snapshot.yml b/tests/__snapshots__/gcm-nonce-reuse-java-snapshot.yml new file mode 100644 index 00000000..91128348 --- /dev/null +++ b/tests/__snapshots__/gcm-nonce-reuse-java-snapshot.yml @@ -0,0 +1,14 @@ +id: gcm-nonce-reuse-java +snapshots: + ? | + byte[] theBadIV = BAD_IV.getBytes(); + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, theBadIV); + : labels: + - source: GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, theBadIV); + style: primary + start: 37 + end: 124 + - source: byte[] theBadIV = BAD_IV.getBytes(); + style: secondary + start: 0 + end: 36 diff --git a/tests/java/gcm-nonce-reuse-java-test.yml b/tests/java/gcm-nonce-reuse-java-test.yml new file mode 100644 index 00000000..3f5e052e --- /dev/null +++ b/tests/java/gcm-nonce-reuse-java-test.yml @@ -0,0 +1,9 @@ +id: gcm-nonce-reuse-java +valid: + - | + byte[] theBadIV = BAD_IV.getBytes(); + GCMParameterSpec gcmParameter = new GCMParameter(GCM_TAG_LENGTH * 8, theBadIV); +invalid: + - | + byte[] theBadIV = BAD_IV.getBytes(); + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, theBadIV); From c68bd1e194b89235083f43733fc4e00db5d7c693 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Tue, 24 Sep 2024 17:55:46 +0530 Subject: [PATCH 12/41] grpc-client-insecure-connection-go --- .../grpc-client-insecure-connection-go.yml | 20 +++++++++ .../grpc/grpc-client-insecure-connection.yml | 21 --------- ...client-insecure-connection-go-snapshot.yml | 9 ++++ ...pc-client-insecure-connection-snapshot.yml | 43 ------------------- ...rpc-client-insecure-connection-go-test.yml | 7 +++ .../grpc-client-insecure-connection-test.yml | 17 -------- 6 files changed, 36 insertions(+), 81 deletions(-) create mode 100644 rules/go/grpc/grpc-client-insecure-connection-go.yml delete mode 100644 rules/go/grpc/grpc-client-insecure-connection.yml create mode 100644 tests/__snapshots__/grpc-client-insecure-connection-go-snapshot.yml delete mode 100644 tests/__snapshots__/grpc-client-insecure-connection-snapshot.yml create mode 100644 tests/go/grpc-client-insecure-connection-go-test.yml delete mode 100644 tests/go/grpc-client-insecure-connection-test.yml diff --git a/rules/go/grpc/grpc-client-insecure-connection-go.yml b/rules/go/grpc/grpc-client-insecure-connection-go.yml new file mode 100644 index 00000000..f77fdb12 --- /dev/null +++ b/rules/go/grpc/grpc-client-insecure-connection-go.yml @@ -0,0 +1,20 @@ +id: grpc-client-insecure-connection-go +language: go +severity: warning +message: >- + Found an insecure gRPC connection using 'grpc.WithInsecure()'. This + creates a connection without encryption to a gRPC server. A malicious + attacker could tamper with the gRPC message, which could compromise the + machine. Instead, establish a secure connection with an SSL certificate + using the 'grpc.WithTransportCredentials()' function. You can create a + create credentials using a 'tls.Config{}' struct with + 'credentials.NewTLS()'. The final fix looks like this: + 'grpc.WithTransportCredentials(credentials.NewTLS())'. +note: >- + [CWE-300] Channel Accessible by Non-Endpoint. + [REFERENCES] + - https://blog.gopheracademy.com/advent-2019/go-grps-and-tls/#connection-without-encryption +rule: + any: + - pattern: $GRPC.Dial($ADDR, $$$, $GRPC.WithInsecure($$$), $$$) + - pattern: $GRPC.Dial($ADDR, $GRPC.WithInsecure($$$)) diff --git a/rules/go/grpc/grpc-client-insecure-connection.yml b/rules/go/grpc/grpc-client-insecure-connection.yml deleted file mode 100644 index 2e4e6c99..00000000 --- a/rules/go/grpc/grpc-client-insecure-connection.yml +++ /dev/null @@ -1,21 +0,0 @@ -id: grpc-client-insecure-connection -language: go -severity: warning -message: >- - Found an insecure gRPC connection using 'grpc.WithInsecure()'. This creates a - connection without encryption to a gRPC - server. A malicious attacker could tamper with the gRPC message, which could compromise - the machine. Instead, establish - a secure connection with an - SSL certificate using the 'grpc.WithTransportCredentials()' function. You can - create a create credentials using a 'tls.Config{}' - struct with 'credentials.NewTLS()'. The final fix looks like this: 'grpc.WithTransportCredentials(credentials.NewTLS())'. -note: >- - [CWE-300] Channel Accessible by Non-Endpoint - [OWASP A07:2021] Identification and Authentication Failures - [REFERENCES] - - https://blog.gopheracademy.com/advent-2019/go-grps-and-tls/#connection-without-encryption -rule: - any: - - pattern: "$GRPC.Dial($ADDR, $$$, $GRPC.WithInsecure($$$), $$$)" - - pattern: "$GRPC.Dial($ADDR, $$$, $GRPC.WithInsecure($$$))" \ No newline at end of file diff --git a/tests/__snapshots__/grpc-client-insecure-connection-go-snapshot.yml b/tests/__snapshots__/grpc-client-insecure-connection-go-snapshot.yml new file mode 100644 index 00000000..18911bf9 --- /dev/null +++ b/tests/__snapshots__/grpc-client-insecure-connection-go-snapshot.yml @@ -0,0 +1,9 @@ +id: grpc-client-insecure-connection-go +snapshots: + ? | + conn, err := grpc.Dial(address, grpc.WithInsecure()) + : labels: + - source: grpc.Dial(address, grpc.WithInsecure()) + style: primary + start: 13 + end: 52 diff --git a/tests/__snapshots__/grpc-client-insecure-connection-snapshot.yml b/tests/__snapshots__/grpc-client-insecure-connection-snapshot.yml deleted file mode 100644 index 4047934f..00000000 --- a/tests/__snapshots__/grpc-client-insecure-connection-snapshot.yml +++ /dev/null @@ -1,43 +0,0 @@ -id: grpc-client-insecure-connection -snapshots: - ? | - grpc.Dial("example.com", grpc.WithInsecure()) - : labels: - - source: grpc.Dial("example.com", grpc.WithInsecure()) - style: primary - start: 0 - end: 45 - ? | - grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock()) - : labels: - - source: grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock()) - style: primary - start: 0 - end: 63 - ? | - grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second)) - : labels: - - source: grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second)) - style: primary - start: 0 - end: 96 - ? | - grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second), grpc.WithUserAgent("example")) - : labels: - - source: grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second), grpc.WithUserAgent("example")) - style: primary - start: 0 - end: 127 - ? | - grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second), grpc.WithUserAgent("example"), grpc.WithAuthority("example.com")) - : labels: - - source: grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second), grpc.WithUserAgent("example"), grpc.WithAuthority("example.com")) - style: primary - start: 0 - end: 162 - ? grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second), grpc.WithUserAgent("example"), grpc.WithAuthority("example.com"), grpc.WithDial) - : labels: - - source: grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second), grpc.WithUserAgent("example"), grpc.WithAuthority("example.com"), grpc.WithDial) - style: primary - start: 0 - end: 177 diff --git a/tests/go/grpc-client-insecure-connection-go-test.yml b/tests/go/grpc-client-insecure-connection-go-test.yml new file mode 100644 index 00000000..dcd502ef --- /dev/null +++ b/tests/go/grpc-client-insecure-connection-go-test.yml @@ -0,0 +1,7 @@ +id: grpc-client-insecure-connection-go +valid: + - | + conn, err := grpc.Dial(address) +invalid: + - | + conn, err := grpc.Dial(address, grpc.WithInsecure()) diff --git a/tests/go/grpc-client-insecure-connection-test.yml b/tests/go/grpc-client-insecure-connection-test.yml deleted file mode 100644 index 4533f57a..00000000 --- a/tests/go/grpc-client-insecure-connection-test.yml +++ /dev/null @@ -1,17 +0,0 @@ -id: grpc-client-insecure-connection -valid: - - | - grpc.Dial("example.com", grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{}))) -invalid: - - | - grpc.Dial("example.com", grpc.WithInsecure()) - - | - grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock()) - - | - grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second)) - - | - grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second), grpc.WithUserAgent("example")) - - | - grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second), grpc.WithUserAgent("example"), grpc.WithAuthority("example.com")) - - | - grpc.Dial("example.com", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(5*time.Second), grpc.WithUserAgent("example"), grpc.WithAuthority("example.com"), grpc.WithDial) \ No newline at end of file From df25bc753b5d3627e30774be5c132cee9701ae67 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Tue, 24 Sep 2024 17:57:22 +0530 Subject: [PATCH 13/41] avoid-bind-to-all-interfaces-go --- .../avoid-bind-to-all-interfaces-go.yml | 23 +++++++++++++++++++ ...oid-bind-to-all-interfaces-go-snapshot.yml | 16 +++++++++++++ .../avoid-bind-to-all-interfaces-go-test.yml | 9 ++++++++ 3 files changed, 48 insertions(+) create mode 100644 rules/go/security/avoid-bind-to-all-interfaces-go.yml create mode 100644 tests/__snapshots__/avoid-bind-to-all-interfaces-go-snapshot.yml create mode 100644 tests/go/avoid-bind-to-all-interfaces-go-test.yml diff --git a/rules/go/security/avoid-bind-to-all-interfaces-go.yml b/rules/go/security/avoid-bind-to-all-interfaces-go.yml new file mode 100644 index 00000000..7c43714f --- /dev/null +++ b/rules/go/security/avoid-bind-to-all-interfaces-go.yml @@ -0,0 +1,23 @@ +id: avoid-bind-to-all-interfaces-go +language: go +severity: warning +message: >- + "Detected a network listener listening on 0.0.0.0 or an empty string. + This could unexpectedly expose the server publicly as it binds to all + available interfaces. Instead, specify another IP address that is not + 0.0.0.0 nor the empty string." +note: >- + [CWE-200] Exposure of Sensitive Information to an Unauthorized Actor + [REFERENCES] + - https://owasp.org/Top10/A01_2021-Broken_Access_Control +rule: + any: + - pattern: tls.Listen($NETWORK, $IP $$$) + - pattern: net.Listen($NETWORK, $IP $$$) + - pattern: tls.Listen($NETWORK, $IP $$$) + - pattern: net.Listen($NETWORK, $IP $$$) + +constraints: + IP: + kind: interpreted_string_literal + regex: ^"0.0.0.0:.*"$|^":.*"$|^'0.0.0.0:.*'$|^':.*'$ diff --git a/tests/__snapshots__/avoid-bind-to-all-interfaces-go-snapshot.yml b/tests/__snapshots__/avoid-bind-to-all-interfaces-go-snapshot.yml new file mode 100644 index 00000000..7c22130f --- /dev/null +++ b/tests/__snapshots__/avoid-bind-to-all-interfaces-go-snapshot.yml @@ -0,0 +1,16 @@ +id: avoid-bind-to-all-interfaces-go +snapshots: + ? | + l, err := net.Listen("tcp", "0.0.0.0:2000") + : labels: + - source: net.Listen("tcp", "0.0.0.0:2000") + style: primary + start: 10 + end: 43 + ? | + l, err := net.Listen("tcp", ":2000") + : labels: + - source: net.Listen("tcp", ":2000") + style: primary + start: 10 + end: 36 diff --git a/tests/go/avoid-bind-to-all-interfaces-go-test.yml b/tests/go/avoid-bind-to-all-interfaces-go-test.yml new file mode 100644 index 00000000..4aebe122 --- /dev/null +++ b/tests/go/avoid-bind-to-all-interfaces-go-test.yml @@ -0,0 +1,9 @@ +id: avoid-bind-to-all-interfaces-go +valid: + - | + l, err := net.Listen("tcp", "192.168.1.101:2000") +invalid: + - | + l, err := net.Listen("tcp", "0.0.0.0:2000") + - | + l, err := net.Listen("tcp", ":2000") From 3ed4514be8d9abf79f4f9876ef94cdd98176bfd8 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Wed, 25 Sep 2024 10:58:55 +0530 Subject: [PATCH 14/41] Removed duplicates from rule pattern for avoid-bind-to-all-interfaces-go --- rules/go/security/avoid-bind-to-all-interfaces-go.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/rules/go/security/avoid-bind-to-all-interfaces-go.yml b/rules/go/security/avoid-bind-to-all-interfaces-go.yml index 7c43714f..ec13e207 100644 --- a/rules/go/security/avoid-bind-to-all-interfaces-go.yml +++ b/rules/go/security/avoid-bind-to-all-interfaces-go.yml @@ -14,8 +14,6 @@ rule: any: - pattern: tls.Listen($NETWORK, $IP $$$) - pattern: net.Listen($NETWORK, $IP $$$) - - pattern: tls.Listen($NETWORK, $IP $$$) - - pattern: net.Listen($NETWORK, $IP $$$) constraints: IP: From e4992b2ead67317ac231f12e7f91dbfb51d2f5d2 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Wed, 25 Sep 2024 18:01:13 +0530 Subject: [PATCH 15/41] jwt-simple-noverify-js --- .../javascript/jwt/jwt-simple-noverify-js.yml | 45 +++++++++ .../jwt-simple-noverify-js-snapshot.yml | 68 ++++++++++++++ .../jwt-simple-noverify-js-test.yml | 91 +++++++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 rules/javascript/jwt/jwt-simple-noverify-js.yml create mode 100644 tests/__snapshots__/jwt-simple-noverify-js-snapshot.yml create mode 100644 tests/javascript/jwt-simple-noverify-js-test.yml diff --git a/rules/javascript/jwt/jwt-simple-noverify-js.yml b/rules/javascript/jwt/jwt-simple-noverify-js.yml new file mode 100644 index 00000000..9262c5f5 --- /dev/null +++ b/rules/javascript/jwt/jwt-simple-noverify-js.yml @@ -0,0 +1,45 @@ +id: jwt-simple-noverify-js +language: Javascript +severity: warning +message: >- + "Detected the decoding of a JWT token without a verify step. JWT tokens + must be verified before use, otherwise the token's integrity is unknown. + This means a malicious actor could forge a JWT token with any claims. Set + 'verify' to `true` before using the token." +note: >- + [CWE-287] Improper Authentication + [CWE-345] Insufficient Verification of Data Authenticity + [CWE-347] Improper Verification of Cryptographic Signature + [REFERENCES] + - https://www.npmjs.com/package/jwt-simple + - https://cwe.mitre.org/data/definitions/287 + - https://cwe.mitre.org/data/definitions/345 + - https://cwe.mitre.org/data/definitions/347 +rule: + kind: call_expression + any: + - pattern: $JWT.decode($TOKEN, $SECRET, true $$$) + - pattern: $JWT.decode($TOKEN, $SECRET, "$$$" $$$) + - pattern: $JWT.decode($TOKEN, $SECRET, '$$$' $$$) + - pattern: $JWT.decode($TOKEN, $SECRET, `$$$` $$$) + inside: + kind: expression_statement + stopBy: end + follows: + stopBy: end + any: + - kind: lexical_declaration + all: + - has: + stopBy: end + kind: identifier + pattern: $JWT + - has: + stopBy: end + kind: call_expression + pattern: require('jwt-simple') + - kind: expression_statement + has: + stopBy: end + kind: assignment_expression + pattern: $JWT = require('jwt-simple') diff --git a/tests/__snapshots__/jwt-simple-noverify-js-snapshot.yml b/tests/__snapshots__/jwt-simple-noverify-js-snapshot.yml new file mode 100644 index 00000000..3394c951 --- /dev/null +++ b/tests/__snapshots__/jwt-simple-noverify-js-snapshot.yml @@ -0,0 +1,68 @@ +id: jwt-simple-noverify-js +snapshots: + ? "const jwt = require('jwt-simple'); \n\napp.get('/protectedRoute1', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'HS256', 12);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});\n" + : labels: + - source: jwt.decode(token, secretKey, 'HS256', 12) + style: primary + start: 287 + end: 328 + - source: jwt + style: secondary + start: 6 + end: 9 + - source: require('jwt-simple') + style: secondary + start: 12 + end: 33 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + - source: "app.get('/protectedRoute1', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'HS256', 12);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});" + style: secondary + start: 37 + end: 482 + ? "const jwt = require('jwt-simple'); \n\napp.get('/protectedRoute2', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, true);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});\n" + : labels: + - source: jwt.decode(token, secretKey, true) + style: primary + start: 289 + end: 323 + - source: jwt + style: secondary + start: 6 + end: 9 + - source: require('jwt-simple') + style: secondary + start: 12 + end: 33 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + - source: "app.get('/protectedRoute2', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, true);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});" + style: secondary + start: 38 + end: 477 + ? "const jwt = require('jwt-simple'); \n\napp.get('/protectedRoute3', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'false');\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});\n" + : labels: + - source: jwt.decode(token, secretKey, 'false') + style: primary + start: 290 + end: 327 + - source: jwt + style: secondary + start: 6 + end: 9 + - source: require('jwt-simple') + style: secondary + start: 12 + end: 33 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + - source: "app.get('/protectedRoute3', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'false');\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});" + style: secondary + start: 38 + end: 481 diff --git a/tests/javascript/jwt-simple-noverify-js-test.yml b/tests/javascript/jwt-simple-noverify-js-test.yml new file mode 100644 index 00000000..1601fa58 --- /dev/null +++ b/tests/javascript/jwt-simple-noverify-js-test.yml @@ -0,0 +1,91 @@ +id: jwt-simple-noverify-js +valid: + - | + const jwt = require('jwt-simple'); + app.get('/protectedRoute4', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ok: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); + - | + const jwt = require('jwt-simple'); + app.get('/protectedRoute5', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ok: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, false); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); +invalid: + - | + const jwt = require('jwt-simple'); + + app.get('/protectedRoute1', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ruleid: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, 'HS256', 12); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); + - | + const jwt = require('jwt-simple'); + + app.get('/protectedRoute2', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ruleid: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, true); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); + - | + const jwt = require('jwt-simple'); + + app.get('/protectedRoute3', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ruleid: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, 'false'); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); From a8f9725f623a3c27e2555fd9dad7cfd94c8153df Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Wed, 25 Sep 2024 18:03:00 +0530 Subject: [PATCH 16/41] jwt-simple-noverify-ts --- rules/typescript/.gitkeep | 0 .../typescript/jwt/jwt-simple-noverify-ts.yml | 45 +++++++++ .../jwt-simple-noverify-ts-snapshot.yml | 68 ++++++++++++++ tests/typescript/.gitkeep | 0 .../jwt-simple-noverify-ts-test.yml | 91 +++++++++++++++++++ 5 files changed, 204 insertions(+) create mode 100644 rules/typescript/.gitkeep create mode 100644 rules/typescript/jwt/jwt-simple-noverify-ts.yml create mode 100644 tests/__snapshots__/jwt-simple-noverify-ts-snapshot.yml create mode 100644 tests/typescript/.gitkeep create mode 100644 tests/typescript/jwt-simple-noverify-ts-test.yml diff --git a/rules/typescript/.gitkeep b/rules/typescript/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/rules/typescript/jwt/jwt-simple-noverify-ts.yml b/rules/typescript/jwt/jwt-simple-noverify-ts.yml new file mode 100644 index 00000000..e7399695 --- /dev/null +++ b/rules/typescript/jwt/jwt-simple-noverify-ts.yml @@ -0,0 +1,45 @@ +id: jwt-simple-noverify-ts +language: Typescript +severity: warning +message: >- + "Detected the decoding of a JWT token without a verify step. JWT tokens + must be verified before use, otherwise the token's integrity is unknown. + This means a malicious actor could forge a JWT token with any claims. Set + 'verify' to `true` before using the token." +note: >- + [CWE-287] Improper Authentication + [CWE-345] Insufficient Verification of Data Authenticity + [CWE-347] Improper Verification of Cryptographic Signature + [REFERENCES] + - https://www.npmjs.com/package/jwt-simple + - https://cwe.mitre.org/data/definitions/287 + - https://cwe.mitre.org/data/definitions/345 + - https://cwe.mitre.org/data/definitions/347 +rule: + kind: call_expression + any: + - pattern: $JWT.decode($TOKEN, $SECRET, true $$$) + - pattern: $JWT.decode($TOKEN, $SECRET, "$$$" $$$) + - pattern: $JWT.decode($TOKEN, $SECRET, '$$$' $$$) + - pattern: $JWT.decode($TOKEN, $SECRET, `$$$` $$$) + inside: + kind: expression_statement + stopBy: end + follows: + stopBy: end + any: + - kind: lexical_declaration + all: + - has: + stopBy: end + kind: identifier + pattern: $JWT + - has: + stopBy: end + kind: call_expression + pattern: require('jwt-simple') + - kind: expression_statement + has: + stopBy: end + kind: assignment_expression + pattern: $JWT = require('jwt-simple') diff --git a/tests/__snapshots__/jwt-simple-noverify-ts-snapshot.yml b/tests/__snapshots__/jwt-simple-noverify-ts-snapshot.yml new file mode 100644 index 00000000..52b0aea6 --- /dev/null +++ b/tests/__snapshots__/jwt-simple-noverify-ts-snapshot.yml @@ -0,0 +1,68 @@ +id: jwt-simple-noverify-ts +snapshots: + ? "const jwt = require('jwt-simple'); \n\napp.get('/protectedRoute1', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'HS256', 12);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});\n" + : labels: + - source: jwt.decode(token, secretKey, 'HS256', 12) + style: primary + start: 287 + end: 328 + - source: jwt + style: secondary + start: 6 + end: 9 + - source: require('jwt-simple') + style: secondary + start: 12 + end: 33 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + - source: "app.get('/protectedRoute1', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'HS256', 12);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});" + style: secondary + start: 37 + end: 482 + ? "const jwt = require('jwt-simple'); \n\napp.get('/protectedRoute2', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, true);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});\n" + : labels: + - source: jwt.decode(token, secretKey, true) + style: primary + start: 289 + end: 323 + - source: jwt + style: secondary + start: 6 + end: 9 + - source: require('jwt-simple') + style: secondary + start: 12 + end: 33 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + - source: "app.get('/protectedRoute2', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, true);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});" + style: secondary + start: 38 + end: 477 + ? "const jwt = require('jwt-simple'); \n\napp.get('/protectedRoute3', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'false');\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});\n" + : labels: + - source: jwt.decode(token, secretKey, 'false') + style: primary + start: 290 + end: 327 + - source: jwt + style: secondary + start: 6 + end: 9 + - source: require('jwt-simple') + style: secondary + start: 12 + end: 33 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + - source: "app.get('/protectedRoute3', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'false');\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});" + style: secondary + start: 38 + end: 481 diff --git a/tests/typescript/.gitkeep b/tests/typescript/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/typescript/jwt-simple-noverify-ts-test.yml b/tests/typescript/jwt-simple-noverify-ts-test.yml new file mode 100644 index 00000000..55eaeec9 --- /dev/null +++ b/tests/typescript/jwt-simple-noverify-ts-test.yml @@ -0,0 +1,91 @@ +id: jwt-simple-noverify-ts +valid: + - | + const jwt = require('jwt-simple'); + app.get('/protectedRoute4', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ok: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); + - | + const jwt = require('jwt-simple'); + app.get('/protectedRoute5', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ok: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, false); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); +invalid: + - | + const jwt = require('jwt-simple'); + + app.get('/protectedRoute1', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ruleid: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, 'HS256', 12); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); + - | + const jwt = require('jwt-simple'); + + app.get('/protectedRoute2', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ruleid: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, true); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); + - | + const jwt = require('jwt-simple'); + + app.get('/protectedRoute3', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ruleid: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, 'false'); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); From 6e1f903e745aedd929b8cbba144ee0d848fee77c Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Wed, 25 Sep 2024 18:05:31 +0530 Subject: [PATCH 17/41] detect-angular-sce-disabled-javascript --- .../detect-angular-sce-disabled-javascript.yml | 15 +++++++++++++++ ...t-angular-sce-disabled-javascript-snapshot.yml | 9 +++++++++ ...etect-angular-sce-disabled-javascript-test.yml | 7 +++++++ 3 files changed, 31 insertions(+) create mode 100644 rules/javascript/security/detect-angular-sce-disabled-javascript.yml create mode 100644 tests/__snapshots__/detect-angular-sce-disabled-javascript-snapshot.yml create mode 100644 tests/javascript/detect-angular-sce-disabled-javascript-test.yml diff --git a/rules/javascript/security/detect-angular-sce-disabled-javascript.yml b/rules/javascript/security/detect-angular-sce-disabled-javascript.yml new file mode 100644 index 00000000..184059f0 --- /dev/null +++ b/rules/javascript/security/detect-angular-sce-disabled-javascript.yml @@ -0,0 +1,15 @@ +id: detect-angular-sce-disabled-javascript +language: javascript +severity: warning +message: >- + $sceProvider is set to false. Disabling Strict Contextual escaping + (SCE) in an AngularJS application could provide additional attack surface + for XSS vulnerabilities. +note: >- + [CWE-79] Improper Neutralization of Input During Web Page Generation. + [REFERENCES] + - https://docs.angularjs.org/api/ng/service/$sce + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf +rule: + pattern: | + $sceProvider.enabled(false); diff --git a/tests/__snapshots__/detect-angular-sce-disabled-javascript-snapshot.yml b/tests/__snapshots__/detect-angular-sce-disabled-javascript-snapshot.yml new file mode 100644 index 00000000..809d3ff2 --- /dev/null +++ b/tests/__snapshots__/detect-angular-sce-disabled-javascript-snapshot.yml @@ -0,0 +1,9 @@ +id: detect-angular-sce-disabled-javascript +snapshots: + ? | + $sceProvider.enabled(false); + : labels: + - source: $sceProvider.enabled(false); + style: primary + start: 0 + end: 28 diff --git a/tests/javascript/detect-angular-sce-disabled-javascript-test.yml b/tests/javascript/detect-angular-sce-disabled-javascript-test.yml new file mode 100644 index 00000000..965afe1e --- /dev/null +++ b/tests/javascript/detect-angular-sce-disabled-javascript-test.yml @@ -0,0 +1,7 @@ +id: detect-angular-sce-disabled-javascript +valid: + - | + +invalid: + - | + $sceProvider.enabled(false); From c3aaeba90084a3887e10a5caa603b9f0eee9612c Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Wed, 25 Sep 2024 18:06:37 +0530 Subject: [PATCH 18/41] detect-angular-sce-disabled-typescript --- .../detect-angular-sce-disabled-typescript.yml | 15 +++++++++++++++ ...etect-angular-sce-disabled-typescript-test.yml | 7 +++++++ 2 files changed, 22 insertions(+) create mode 100644 rules/typescript/security/detect-angular-sce-disabled-typescript.yml create mode 100644 tests/typescript/detect-angular-sce-disabled-typescript-test.yml diff --git a/rules/typescript/security/detect-angular-sce-disabled-typescript.yml b/rules/typescript/security/detect-angular-sce-disabled-typescript.yml new file mode 100644 index 00000000..68c6f54c --- /dev/null +++ b/rules/typescript/security/detect-angular-sce-disabled-typescript.yml @@ -0,0 +1,15 @@ +id: detect-angular-sce-disabled-typescript +language: typescript +severity: warning +message: >- + $sceProvider is set to false. Disabling Strict Contextual escaping + (SCE) in an AngularJS application could provide additional attack surface + for XSS vulnerabilities. +note: >- + [CWE-79] Improper Neutralization of Input During Web Page Generation. + [REFERENCES] + - https://docs.angularjs.org/api/ng/service/$sce + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf +rule: + pattern: | + $sceProvider.enabled(false); diff --git a/tests/typescript/detect-angular-sce-disabled-typescript-test.yml b/tests/typescript/detect-angular-sce-disabled-typescript-test.yml new file mode 100644 index 00000000..541d83e7 --- /dev/null +++ b/tests/typescript/detect-angular-sce-disabled-typescript-test.yml @@ -0,0 +1,7 @@ +id: detect-angular-sce-disabled-typescript +valid: + - | + +invalid: + - | + $sceProvider.enabled(false); From 88bd8dc30fe64b36b8667f5b5b95a0e012fe2434 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Wed, 25 Sep 2024 18:08:23 +0530 Subject: [PATCH 19/41] jwt-go-none-algorithm-go --- rules/go/jwt-go/jwt-go-none-algorithm-go.yml | 38 +++++++++++++++ ...gular-sce-disabled-typescript-snapshot.yml | 9 ++++ .../jwt-go-none-algorithm-go-snapshot.yml | 46 +++++++++++++++++++ tests/go/jwt-go-none-algorithm-go-test.yml | 28 +++++++++++ 4 files changed, 121 insertions(+) create mode 100644 rules/go/jwt-go/jwt-go-none-algorithm-go.yml create mode 100644 tests/__snapshots__/detect-angular-sce-disabled-typescript-snapshot.yml create mode 100644 tests/__snapshots__/jwt-go-none-algorithm-go-snapshot.yml create mode 100644 tests/go/jwt-go-none-algorithm-go-test.yml diff --git a/rules/go/jwt-go/jwt-go-none-algorithm-go.yml b/rules/go/jwt-go/jwt-go-none-algorithm-go.yml new file mode 100644 index 00000000..5a40fa82 --- /dev/null +++ b/rules/go/jwt-go/jwt-go-none-algorithm-go.yml @@ -0,0 +1,38 @@ +id: jwt-go-none-algorithm-go +language: go +severity: warning +message: >- + Detected use of the 'none' algorithm in a JWT token. The 'none' + algorithm assumes the integrity of the token has already been verified. + This would allow a malicious actor to forge a JWT token that will + automatically be verified. Do not explicitly use the 'none' algorithm. + Instead, use an algorithm such as 'HS256'. +note: >- + [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm + [OWASP A03:2017]: Sensitive Data Exposure + [OWASP A02:2021]: Cryptographic Failures + [REFERENCES] + https://owasp.org/Top10/A02_2021-Cryptographic_Failures +utils: + after_declaration: + inside: + stopBy: end + kind: function_declaration + follows: + stopBy: end + kind: import_declaration + has: + stopBy: end + kind: import_spec_list + pattern: $IMPORT_MOD +rule: + kind: selector_expression + all: + - pattern: $JWT_FUNC + - matches: after_declaration + +constraints: + JWT_FUNC: + regex: (jwt.SigningMethodNone|jwt.UnsafeAllowNoneSignatureType) + IMPORT_MOD: + regex: ("github.com/golang-jwt/jwt"|"github.com/dgrijalva/jwt-go") diff --git a/tests/__snapshots__/detect-angular-sce-disabled-typescript-snapshot.yml b/tests/__snapshots__/detect-angular-sce-disabled-typescript-snapshot.yml new file mode 100644 index 00000000..8142ea9d --- /dev/null +++ b/tests/__snapshots__/detect-angular-sce-disabled-typescript-snapshot.yml @@ -0,0 +1,9 @@ +id: detect-angular-sce-disabled-typescript +snapshots: + ? | + $sceProvider.enabled(false); + : labels: + - source: $sceProvider.enabled(false); + style: primary + start: 0 + end: 28 diff --git a/tests/__snapshots__/jwt-go-none-algorithm-go-snapshot.yml b/tests/__snapshots__/jwt-go-none-algorithm-go-snapshot.yml new file mode 100644 index 00000000..b6d7e06b --- /dev/null +++ b/tests/__snapshots__/jwt-go-none-algorithm-go-snapshot.yml @@ -0,0 +1,46 @@ +id: jwt-go-none-algorithm-go +snapshots: + ? | + import ( + "fmt" + "github.com/dgrijalva/jwt-go" + ) + func bad1(key []byte) { + claims = jwt.StandardClaims{ + ExpiresAt:15000, + Issuer:"test",} + token = jwt.NewWithClaims(jwt.SigningMethodNone, claims) + ss, err = token.SignedString(jwt.UnsafeAllowNoneSignatureType) + fmt.Printf("%v %v\n", ss, err)} + : labels: + - source: jwt.SigningMethodNone + style: primary + start: 170 + end: 191 + - source: |- + ( + "fmt" + "github.com/dgrijalva/jwt-go" + ) + style: secondary + start: 7 + end: 51 + - source: |- + import ( + "fmt" + "github.com/dgrijalva/jwt-go" + ) + style: secondary + start: 0 + end: 51 + - source: |- + func bad1(key []byte) { + claims = jwt.StandardClaims{ + ExpiresAt:15000, + Issuer:"test",} + token = jwt.NewWithClaims(jwt.SigningMethodNone, claims) + ss, err = token.SignedString(jwt.UnsafeAllowNoneSignatureType) + fmt.Printf("%v %v\n", ss, err)} + style: secondary + start: 52 + end: 295 diff --git a/tests/go/jwt-go-none-algorithm-go-test.yml b/tests/go/jwt-go-none-algorithm-go-test.yml new file mode 100644 index 00000000..a44a170c --- /dev/null +++ b/tests/go/jwt-go-none-algorithm-go-test.yml @@ -0,0 +1,28 @@ +id: jwt-go-none-algorithm-go +valid: + - | + import ( + "fmt" + "github.com/dgrijalva/jwt-go" + ) + func ok1(key []byte){ + claims = jwt.StandardClaims{ + ExpiresAt:15000, + Issuer:"test",} + token = jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + ss, err = token.SignedString(key) + fmt.Printf("%v %v\n", ss, err)} + +invalid: + - | + import ( + "fmt" + "github.com/dgrijalva/jwt-go" + ) + func bad1(key []byte) { + claims = jwt.StandardClaims{ + ExpiresAt:15000, + Issuer:"test",} + token = jwt.NewWithClaims(jwt.SigningMethodNone, claims) + ss, err = token.SignedString(jwt.UnsafeAllowNoneSignatureType) + fmt.Printf("%v %v\n", ss, err)} From fbed6dc805c1e19abed4d9cbfe5bc6c236e8a745 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 26 Sep 2024 18:44:00 +0530 Subject: [PATCH 20/41] Fixed changes suggested by bot --- rules/javascript/jwt/jwt-simple-noverify-js.yml | 2 +- rules/typescript/jwt/jwt-simple-noverify-ts.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/javascript/jwt/jwt-simple-noverify-js.yml b/rules/javascript/jwt/jwt-simple-noverify-js.yml index 9262c5f5..09f57f28 100644 --- a/rules/javascript/jwt/jwt-simple-noverify-js.yml +++ b/rules/javascript/jwt/jwt-simple-noverify-js.yml @@ -1,5 +1,5 @@ id: jwt-simple-noverify-js -language: Javascript +language: JavaScript severity: warning message: >- "Detected the decoding of a JWT token without a verify step. JWT tokens diff --git a/rules/typescript/jwt/jwt-simple-noverify-ts.yml b/rules/typescript/jwt/jwt-simple-noverify-ts.yml index e7399695..2f58eb0f 100644 --- a/rules/typescript/jwt/jwt-simple-noverify-ts.yml +++ b/rules/typescript/jwt/jwt-simple-noverify-ts.yml @@ -1,5 +1,5 @@ id: jwt-simple-noverify-ts -language: Typescript +language: TypeScript severity: warning message: >- "Detected the decoding of a JWT token without a verify step. JWT tokens From 66f97353e57cc40e0606e1746e889709a1efc213 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 26 Sep 2024 18:45:39 +0530 Subject: [PATCH 21/41] more changes by bot --- .../jwt-go-none-algorithm-go-snapshot.yml | 44 +++++++++++++++++++ tests/go/jwt-go-none-algorithm-go-test.yml | 6 +-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/tests/__snapshots__/jwt-go-none-algorithm-go-snapshot.yml b/tests/__snapshots__/jwt-go-none-algorithm-go-snapshot.yml index b6d7e06b..17c8ceef 100644 --- a/tests/__snapshots__/jwt-go-none-algorithm-go-snapshot.yml +++ b/tests/__snapshots__/jwt-go-none-algorithm-go-snapshot.yml @@ -1,5 +1,49 @@ id: jwt-go-none-algorithm-go snapshots: + ? | + import ( + "fmt" + "github.com/dgrijalva/jwt-go" + ) + func bad1(key []byte) { + claims := jwt.StandardClaims{ + ExpiresAt:15000, + Issuer:"test",} + token := jwt.NewWithClaims(jwt.SigningMethodNone, claims) + ss, err := token.SignedString(jwt.UnsafeAllowNoneSignatureType) + fmt.Printf("%v %v\n", ss, err)} + : labels: + - source: jwt.SigningMethodNone + style: primary + start: 172 + end: 193 + - source: |- + ( + "fmt" + "github.com/dgrijalva/jwt-go" + ) + style: secondary + start: 7 + end: 51 + - source: |- + import ( + "fmt" + "github.com/dgrijalva/jwt-go" + ) + style: secondary + start: 0 + end: 51 + - source: |- + func bad1(key []byte) { + claims := jwt.StandardClaims{ + ExpiresAt:15000, + Issuer:"test",} + token := jwt.NewWithClaims(jwt.SigningMethodNone, claims) + ss, err := token.SignedString(jwt.UnsafeAllowNoneSignatureType) + fmt.Printf("%v %v\n", ss, err)} + style: secondary + start: 52 + end: 298 ? | import ( "fmt" diff --git a/tests/go/jwt-go-none-algorithm-go-test.yml b/tests/go/jwt-go-none-algorithm-go-test.yml index a44a170c..d3c1681f 100644 --- a/tests/go/jwt-go-none-algorithm-go-test.yml +++ b/tests/go/jwt-go-none-algorithm-go-test.yml @@ -20,9 +20,9 @@ invalid: "github.com/dgrijalva/jwt-go" ) func bad1(key []byte) { - claims = jwt.StandardClaims{ + claims := jwt.StandardClaims{ ExpiresAt:15000, Issuer:"test",} - token = jwt.NewWithClaims(jwt.SigningMethodNone, claims) - ss, err = token.SignedString(jwt.UnsafeAllowNoneSignatureType) + token := jwt.NewWithClaims(jwt.SigningMethodNone, claims) + ss, err := token.SignedString(jwt.UnsafeAllowNoneSignatureType) fmt.Printf("%v %v\n", ss, err)} From d298eecd399544ba6e6b66d2b59e2c8034ef251b Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 26 Sep 2024 18:47:41 +0530 Subject: [PATCH 22/41] small-key-size-c --- rules/c/security/small-key-size-c.yml | 56 +++++++++++++++++++ .../small-key-size-c-snapshot.yml | 50 +++++++++++++++++ tests/c/small-key-size-c-test.yml | 26 +++++++++ 3 files changed, 132 insertions(+) create mode 100644 rules/c/security/small-key-size-c.yml create mode 100644 tests/__snapshots__/small-key-size-c-snapshot.yml create mode 100644 tests/c/small-key-size-c-test.yml diff --git a/rules/c/security/small-key-size-c.yml b/rules/c/security/small-key-size-c.yml new file mode 100644 index 00000000..661c9a41 --- /dev/null +++ b/rules/c/security/small-key-size-c.yml @@ -0,0 +1,56 @@ +id: small-key-size-c +language: c +severity: warning +message: >- + $KEY_FUNCTION` is using a key size of only $KEY_BITS bits. This is + less than the recommended key size of 2048 bits. +note: >- + [CWE-326]: Inadequate Encryption Strength + [OWASP A02:2021]: Cryptographic Failures + [OWASP A03:2017]: Sensitive Data Exposure + [REFERENCES] + https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf + https://owasp.org/Top10/A02_2021-Cryptographic_Failures +utils: + Match_pattern_with_prefix_statement: + kind: expression_statement + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $AST + - has: + stopBy: end + kind: argument_list + has: + stopby: end + kind: identifier + pattern: $Q + - follows: + stopBy: end + kind: declaration + has: + stopBy: end + kind: init_declarator + all: + - has: + stopBy: end + kind: identifier + pattern: $Q + - has: + stopBy: end + kind: number_literal + pattern: $AASS + +rule: + kind: expression_statement + matches: Match_pattern_with_prefix_statement +constraints: + AST: + regex: (DH_generate_parameters_ex|DSA_generate_parameters_ex|EVP_PKEY_CTX_set_dh_paramgen_prime_len|EVP_PKEY_CTX_set_dsa_paramgen_bits|EVP_PKEY_CTX_set_rsa_keygen_bits|RSA_generate_key_ex|RSA_generate_key_fips) + AASS: + regex: '^(-?(0|[1-9][0-9]?|[1-9][0-9]{2}|1[0-9]{3}|20[0-3][0-9]|204[0-7])(\.[0-9]+)?|0|-[1-9][0-9]*|-[1-9][0-9]{2,}|-1[0-9]{3}|-20[0-3][0-9]|-204[0-7])$' diff --git a/tests/__snapshots__/small-key-size-c-snapshot.yml b/tests/__snapshots__/small-key-size-c-snapshot.yml new file mode 100644 index 00000000..bdfd49e0 --- /dev/null +++ b/tests/__snapshots__/small-key-size-c-snapshot.yml @@ -0,0 +1,50 @@ +id: small-key-size-c +snapshots: + ? | + void foo() { + size_t bad_size = 1024; + size_t good_size = 2048; + DH_generate_parameters_ex(NULL, bad_size); + DSA_generate_parameters_ex(NULL, bad_size); + EVP_PKEY_CTX_set_dh_paramgen_prime_len(NULL, bad_size); + EVP_PKEY_CTX_set_dsa_paramgen_bits(NULL, bad_size); + EVP_PKEY_CTX_set_rsa_keygen_bits(NULL, bad_size); + RSA_generate_key_ex(NULL, bad_size); + RSA_generate_key_fips(NULL, bad_size);} + : labels: + - source: DH_generate_parameters_ex(NULL, bad_size); + style: primary + start: 62 + end: 104 + - source: DH_generate_parameters_ex + style: secondary + start: 62 + end: 87 + - source: bad_size + style: secondary + start: 94 + end: 102 + - source: (NULL, bad_size) + style: secondary + start: 87 + end: 103 + - source: DH_generate_parameters_ex(NULL, bad_size) + style: secondary + start: 62 + end: 103 + - source: bad_size + style: secondary + start: 20 + end: 28 + - source: '1024' + style: secondary + start: 31 + end: 35 + - source: bad_size = 1024 + style: secondary + start: 20 + end: 35 + - source: size_t bad_size = 1024; + style: secondary + start: 13 + end: 36 diff --git a/tests/c/small-key-size-c-test.yml b/tests/c/small-key-size-c-test.yml new file mode 100644 index 00000000..e4c3a272 --- /dev/null +++ b/tests/c/small-key-size-c-test.yml @@ -0,0 +1,26 @@ +id: small-key-size-c +valid: + - | + void foo() { + size_t bad_size = 1024; + size_t good_size = 2048; + DH_generate_parameters_ex(NULL, good_size); + DSA_generate_parameters_ex(NULL, good_size); + EVP_PKEY_CTX_set_dh_paramgen_prime_len(NULL, good_size); + EVP_PKEY_CTX_set_dsa_paramgen_bits(NULL, good_size); + EVP_PKEY_CTX_set_rsa_keygen_bits(NULL, good_size); + RSA_generate_key_ex(NULL, good_size); + RSA_generate_key_fips(NULL, good_size);} + +invalid: + - | + void foo() { + size_t bad_size = 1024; + size_t good_size = 2048; + DH_generate_parameters_ex(NULL, bad_size); + DSA_generate_parameters_ex(NULL, bad_size); + EVP_PKEY_CTX_set_dh_paramgen_prime_len(NULL, bad_size); + EVP_PKEY_CTX_set_dsa_paramgen_bits(NULL, bad_size); + EVP_PKEY_CTX_set_rsa_keygen_bits(NULL, bad_size); + RSA_generate_key_ex(NULL, bad_size); + RSA_generate_key_fips(NULL, bad_size);} From 623523694a81546ffd3f6fbbb64375e794311c27 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 26 Sep 2024 18:48:53 +0530 Subject: [PATCH 23/41] simple-command-injection-direct-input-java --- ...le-command-injection-direct-input-java.yml | 56 ++++++++ ...d-injection-direct-input-java-snapshot.yml | 126 ++++++++++++++++++ ...mmand-injection-direct-input-java-test.yml | 59 ++++++++ 3 files changed, 241 insertions(+) create mode 100644 rules/java/security/simple-command-injection-direct-input-java.yml create mode 100644 tests/__snapshots__/simple-command-injection-direct-input-java-snapshot.yml create mode 100644 tests/java/simple-command-injection-direct-input-java-test.yml diff --git a/rules/java/security/simple-command-injection-direct-input-java.yml b/rules/java/security/simple-command-injection-direct-input-java.yml new file mode 100644 index 00000000..ad7f3e6e --- /dev/null +++ b/rules/java/security/simple-command-injection-direct-input-java.yml @@ -0,0 +1,56 @@ +id: simple-command-injection-direct-input-java +language: java +severity: warning +message: >- + "Untrusted input might be injected into a command executed by the + application, which can lead to a command injection vulnerability. An + attacker can execute arbitrary commands, potentially gaining complete + control of the system. To prevent this vulnerability, avoid executing OS + commands with user input. If this is unavoidable, validate and sanitize + the input, and use safe methods for executing the commands. For more + information, see: [Java command injection + prevention](https://semgrep.dev/docs/cheat-sheets/java-command-injection/\ + )" +note: >- + [CWE-78] Improper Neutralization of Special Elements used in an OS + [REFERENCES] + - https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html + - https://owasp.org/Top10/A03_2021-Injection + +rule: + kind: method_invocation + pattern: Runtime.getRuntime().exec($SOURCE) + inside: + kind: method_declaration + stopBy: end + has: + stopBy: end + kind: formal_parameter + has: + kind: modifiers + any: + - has: + kind: marker_annotation + has: + kind: identifier + pattern: $REQ + - has: + kind: annotation + all: + - has: + kind: identifier + pattern: $REQ + - has: + kind: annotation_argument_list + precedes: + kind: type_identifier + pattern: $TYPE + precedes: + kind: identifier + pattern: $SOURCE + +constraints: + REQ: + regex: ^(RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue|ModelAttribute) + TYPE: + regex: ^[^I].*|^I[^n].*|^In[^t].*|^Int[^e].*|^Inte[^g].*|^Integ[^e].*|^Inge[^r].*|^L[^o].*|^Lo[^n].*|^Lon[^g].*|^F[^l].*|^Fl[^o].*|^Flo[^a].*|^Floa[^t].*|^D[^o].*|^Do[^u].*|^Dou[^b].*|^Doub[^l].*|^Doubl[^e].*|^C[^h].*|^Ch[^a].*|^Cha[^r].*|^B[^o].*|^Bo[^o].*|^Boo[^l].*|^Bool[^e].*|^Boole[^a].*|^Boolea[^n].*|^i[^n].*|^in[^t].*|^l[^o].*|^lo[^n].*|^lon[^g].*|^f[^l].*|^fl[^o].*|^flo[^a].*|^floa[^t].*|^d[^o].*|^do[^u].*|^dou[^b].*|^doub[^l].*|^doubl[^e].*|^c[^h].*|^ch[^a].*|^cha[^r].*|^b[^o].*|^bo[^o].*|^boo[^l].*|^bool[^e].*|^boole[^a].*|^boolea[^n].* diff --git a/tests/__snapshots__/simple-command-injection-direct-input-java-snapshot.yml b/tests/__snapshots__/simple-command-injection-direct-input-java-snapshot.yml new file mode 100644 index 00000000..22d0b82e --- /dev/null +++ b/tests/__snapshots__/simple-command-injection-direct-input-java-snapshot.yml @@ -0,0 +1,126 @@ +id: simple-command-injection-direct-input-java +snapshots: + ? | + @GetMapping("/run/{command}") + public ResponseEntity run_direct_from_jumbo( + @PathVariable final String command + ) { + ResponseEntity response = ResponseEntity.noContent().build(); + try { + Runtime.getRuntime().exec(command); + } catch (IOException e) { + response = ResponseEntity.badRequest().build(); + } + + return response; + } + : labels: + - source: Runtime.getRuntime().exec(command) + style: primary + start: 208 + end: 242 + - source: PathVariable + style: secondary + start: 83 + end: 95 + - source: '@PathVariable' + style: secondary + start: 82 + end: 95 + - source: command + style: secondary + start: 109 + end: 116 + - source: String + style: secondary + start: 102 + end: 108 + - source: '@PathVariable final' + style: secondary + start: 82 + end: 101 + - source: '@PathVariable final String command' + style: secondary + start: 82 + end: 116 + - source: |- + @GetMapping("/run/{command}") + public ResponseEntity run_direct_from_jumbo( + @PathVariable final String command + ) { + ResponseEntity response = ResponseEntity.noContent().build(); + try { + Runtime.getRuntime().exec(command); + } catch (IOException e) { + response = ResponseEntity.badRequest().build(); + } + + return response; + } + style: secondary + start: 0 + end: 358 + ? | + @GetMapping("/run/{command}") + public ResponseEntity run_direct_from_jumbo( + @PathVariable() final String command + ) { + ResponseEntity response = ResponseEntity.noContent().build(); + try { + Runtime.getRuntime().exec(command); + } catch (IOException e) { + response = ResponseEntity.badRequest().build(); + } + + return response; + } + : labels: + - source: Runtime.getRuntime().exec(command) + style: primary + start: 210 + end: 244 + - source: PathVariable + style: secondary + start: 83 + end: 95 + - source: () + style: secondary + start: 95 + end: 97 + - source: '@PathVariable()' + style: secondary + start: 82 + end: 97 + - source: command + style: secondary + start: 111 + end: 118 + - source: String + style: secondary + start: 104 + end: 110 + - source: '@PathVariable() final' + style: secondary + start: 82 + end: 103 + - source: '@PathVariable() final String command' + style: secondary + start: 82 + end: 118 + - source: |- + @GetMapping("/run/{command}") + public ResponseEntity run_direct_from_jumbo( + @PathVariable() final String command + ) { + ResponseEntity response = ResponseEntity.noContent().build(); + try { + Runtime.getRuntime().exec(command); + } catch (IOException e) { + response = ResponseEntity.badRequest().build(); + } + + return response; + } + style: secondary + start: 0 + end: 360 diff --git a/tests/java/simple-command-injection-direct-input-java-test.yml b/tests/java/simple-command-injection-direct-input-java-test.yml new file mode 100644 index 00000000..cba713e4 --- /dev/null +++ b/tests/java/simple-command-injection-direct-input-java-test.yml @@ -0,0 +1,59 @@ +id: simple-command-injection-direct-input-java +valid: + - | + @GetMapping("/run/{command}") + public ResponseEntity run1( + @PathVariable final String command + ) { + ResponseEntity response = ResponseEntity.noContent().build(); + try { + String foo = command + "something something..."; + Runtime.getRuntime().exec(foo); + } catch (IOException e) { + response = ResponseEntity.badRequest().build(); + } + return response; + } + - | + @GetMapping("/run/{command}") + public ResponseEntity ok( + @PathVariable final String command + ) { + ResponseEntity response = ResponseEntity.noContent().build(); + try { + Runtime.getRuntime().exec("/bin/ls"); + } catch (IOException e) { + response = ResponseEntity.badRequest().build(); + } + + return response; + } +invalid: + - | + @GetMapping("/run/{command}") + public ResponseEntity run_direct_from_jumbo( + @PathVariable() final String command + ) { + ResponseEntity response = ResponseEntity.noContent().build(); + try { + Runtime.getRuntime().exec(command); + } catch (IOException e) { + response = ResponseEntity.badRequest().build(); + } + + return response; + } + - | + @GetMapping("/run/{command}") + public ResponseEntity run_direct_from_jumbo( + @PathVariable final String command + ) { + ResponseEntity response = ResponseEntity.noContent().build(); + try { + Runtime.getRuntime().exec(command); + } catch (IOException e) { + response = ResponseEntity.badRequest().build(); + } + + return response; + } From e621b4e2554e08940e38b1b6899731483962f016 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 26 Sep 2024 18:51:13 +0530 Subject: [PATCH 24/41] jwt-none-alg-typescript --- .../jwt/jwt-none-alg-typescript.yml | 46 +++++++++++++++++++ .../jwt-none-alg-typescript-snapshot.yml | 19 ++++++++ .../jwt-none-alg-typescript-test.yml | 9 ++++ 3 files changed, 74 insertions(+) create mode 100644 rules/typescript/jwt/jwt-none-alg-typescript.yml create mode 100644 tests/__snapshots__/jwt-none-alg-typescript-snapshot.yml create mode 100644 tests/typescript/jwt-none-alg-typescript-test.yml diff --git a/rules/typescript/jwt/jwt-none-alg-typescript.yml b/rules/typescript/jwt/jwt-none-alg-typescript.yml new file mode 100644 index 00000000..1badeba2 --- /dev/null +++ b/rules/typescript/jwt/jwt-none-alg-typescript.yml @@ -0,0 +1,46 @@ +id: jwt-none-alg-typescript +language: typescript +severity: warning +message: >- + Detected use of the 'none' algorithm in a JWT token. The 'none' + algorithm assumes the integrity of the token has already been verified. + This would allow a malicious actor to forge a JWT token that will + automatically be verified. Do not explicitly use the 'none' algorithm. + Instead, use an algorithm such as 'HS256'. +note: >- + [CWE-327] Use of a Broken or Risky Cryptographic Algorithm. + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + any: + - pattern: const $T = JWT.verify($P, JWK.None); + follows: + pattern: const { JWK, JWT } = $JOSE; + follows: + pattern: const $JOSE = require("jose"); + - pattern: $T = JWT.verify($P, JWK.None); + follows: + pattern: const { JWK, JWT } = $JOSE; + follows: + pattern: const $JOSE = require("jose"); + - pattern: JWT.verify($P, JWK.None); + follows: + pattern: const { JWK, JWT } = $JOSE; + follows: + pattern: const $JOSE = require("jose"); + + - pattern: var $T = JWT.verify($P, JWK.None); + follows: + pattern: var { JWK, JWT } = $JOSE; + follows: + pattern: var $JOSE = require("jose"); + - pattern: $T = JWT.verify($P, JWK.None); + follows: + pattern: var { JWK, JWT } = $JOSE; + follows: + pattern: var $JOSE = require("jose"); + - pattern: JWT.verify($P, JWK.None); + follows: + pattern: var { JWK, JWT } = $JOSE; + follows: + pattern: var $JOSE = require("jose"); diff --git a/tests/__snapshots__/jwt-none-alg-typescript-snapshot.yml b/tests/__snapshots__/jwt-none-alg-typescript-snapshot.yml new file mode 100644 index 00000000..1cb4f8a7 --- /dev/null +++ b/tests/__snapshots__/jwt-none-alg-typescript-snapshot.yml @@ -0,0 +1,19 @@ +id: jwt-none-alg-typescript +snapshots: + ? | + const jose = require("jose"); + const { JWK, JWT } = jose; + const token = JWT.verify('token-here', JWK.None); + : labels: + - source: const token = JWT.verify('token-here', JWK.None); + style: primary + start: 57 + end: 106 + - source: const jose = require("jose"); + style: secondary + start: 0 + end: 29 + - source: const { JWK, JWT } = jose; + style: secondary + start: 30 + end: 56 diff --git a/tests/typescript/jwt-none-alg-typescript-test.yml b/tests/typescript/jwt-none-alg-typescript-test.yml new file mode 100644 index 00000000..b0c89b0f --- /dev/null +++ b/tests/typescript/jwt-none-alg-typescript-test.yml @@ -0,0 +1,9 @@ +id: jwt-none-alg-typescript +valid: + - | + +invalid: + - | + const jose = require("jose"); + const { JWK, JWT } = jose; + const token = JWT.verify('token-here', JWK.None); From a03697c0bc57a0ac60c8c0a887ed2b5feebdfa7c Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 26 Sep 2024 18:52:27 +0530 Subject: [PATCH 25/41] jwt-none-alg-javascript --- .../jwt/jwt-none-alg-javascript.yml | 46 +++++++++++++++++++ .../jwt-none-alg-javascript-snapshot.yml | 19 ++++++++ .../jwt-none-alg-javascript-test.yml | 9 ++++ 3 files changed, 74 insertions(+) create mode 100644 rules/javascript/jwt/jwt-none-alg-javascript.yml create mode 100644 tests/__snapshots__/jwt-none-alg-javascript-snapshot.yml create mode 100644 tests/javascript/jwt-none-alg-javascript-test.yml diff --git a/rules/javascript/jwt/jwt-none-alg-javascript.yml b/rules/javascript/jwt/jwt-none-alg-javascript.yml new file mode 100644 index 00000000..d5234c1b --- /dev/null +++ b/rules/javascript/jwt/jwt-none-alg-javascript.yml @@ -0,0 +1,46 @@ +id: jwt-none-alg-javascript +language: javascript +severity: warning +message: >- + Detected use of the 'none' algorithm in a JWT token. The 'none' + algorithm assumes the integrity of the token has already been verified. + This would allow a malicious actor to forge a JWT token that will + automatically be verified. Do not explicitly use the 'none' algorithm. + Instead, use an algorithm such as 'HS256'. +note: >- + [CWE-327] Use of a Broken or Risky Cryptographic Algorithm. + [REFERENCES] + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures +rule: + any: + - pattern: const $T = JWT.verify($P, JWK.None); + follows: + pattern: const { JWK, JWT } = $JOSE; + follows: + pattern: const $JOSE = require("jose"); + - pattern: $T = JWT.verify($P, JWK.None); + follows: + pattern: const { JWK, JWT } = $JOSE; + follows: + pattern: const $JOSE = require("jose"); + - pattern: JWT.verify($P, JWK.None); + follows: + pattern: const { JWK, JWT } = $JOSE; + follows: + pattern: const $JOSE = require("jose"); + + - pattern: var $T = JWT.verify($P, JWK.None); + follows: + pattern: var { JWK, JWT } = $JOSE; + follows: + pattern: var $JOSE = require("jose"); + - pattern: $T = JWT.verify($P, JWK.None); + follows: + pattern: var { JWK, JWT } = $JOSE; + follows: + pattern: var $JOSE = require("jose"); + - pattern: JWT.verify($P, JWK.None); + follows: + pattern: var { JWK, JWT } = $JOSE; + follows: + pattern: var $JOSE = require("jose"); diff --git a/tests/__snapshots__/jwt-none-alg-javascript-snapshot.yml b/tests/__snapshots__/jwt-none-alg-javascript-snapshot.yml new file mode 100644 index 00000000..d1fe39db --- /dev/null +++ b/tests/__snapshots__/jwt-none-alg-javascript-snapshot.yml @@ -0,0 +1,19 @@ +id: jwt-none-alg-javascript +snapshots: + ? | + const jose = require("jose"); + const { JWK, JWT } = jose; + const token = JWT.verify('token-here', JWK.None); + : labels: + - source: const token = JWT.verify('token-here', JWK.None); + style: primary + start: 57 + end: 106 + - source: const jose = require("jose"); + style: secondary + start: 0 + end: 29 + - source: const { JWK, JWT } = jose; + style: secondary + start: 30 + end: 56 diff --git a/tests/javascript/jwt-none-alg-javascript-test.yml b/tests/javascript/jwt-none-alg-javascript-test.yml new file mode 100644 index 00000000..11ef4c36 --- /dev/null +++ b/tests/javascript/jwt-none-alg-javascript-test.yml @@ -0,0 +1,9 @@ +id: jwt-none-alg-javascript +valid: + - | + +invalid: + - | + const jose = require("jose"); + const { JWK, JWT } = jose; + const token = JWT.verify('token-here', JWK.None); From 7587e4953c221c79e9b70149d89eb09b05e2979b Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 27 Sep 2024 17:54:25 +0530 Subject: [PATCH 26/41] small-key-size-c++ --- rules/cpp/security/small-key-size-cpp.yml | 56 +++++++++++++++++++ .../small-key-size-c++-snapshot.yml | 50 +++++++++++++++++ tests/cpp/small-key-size-cpp-test.yml | 26 +++++++++ 3 files changed, 132 insertions(+) create mode 100644 rules/cpp/security/small-key-size-cpp.yml create mode 100644 tests/__snapshots__/small-key-size-c++-snapshot.yml create mode 100644 tests/cpp/small-key-size-cpp-test.yml diff --git a/rules/cpp/security/small-key-size-cpp.yml b/rules/cpp/security/small-key-size-cpp.yml new file mode 100644 index 00000000..631995ec --- /dev/null +++ b/rules/cpp/security/small-key-size-cpp.yml @@ -0,0 +1,56 @@ +id: small-key-size-c++ +language: c +severity: warning +message: >- + $KEY_FUNCTION` is using a key size of only $KEY_BITS bits. This is + less than the recommended key size of 2048 bits. +note: >- + [CWE-326]: Inadequate Encryption Strength + [OWASP A02:2021]: Cryptographic Failures + [OWASP A03:2017]: Sensitive Data Exposure + [REFERENCES] + https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf + https://owasp.org/Top10/A02_2021-Cryptographic_Failures +utils: + Match_pattern_with_prefix_statement: + kind: expression_statement + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $AST + - has: + stopBy: end + kind: argument_list + has: + stopby: end + kind: identifier + pattern: $Q + - follows: + stopBy: end + kind: declaration + has: + stopBy: end + kind: init_declarator + all: + - has: + stopBy: end + kind: identifier + pattern: $Q + - has: + stopBy: end + kind: number_literal + pattern: $AASS + +rule: + kind: expression_statement + matches: Match_pattern_with_prefix_statement +constraints: + AST: + regex: (DH_generate_parameters_ex|DSA_generate_parameters_ex|EVP_PKEY_CTX_set_dh_paramgen_prime_len|EVP_PKEY_CTX_set_dsa_paramgen_bits|EVP_PKEY_CTX_set_rsa_keygen_bits|RSA_generate_key_ex|RSA_generate_key_fips) + AASS: + regex: '^(-?(0|[1-9][0-9]?|[1-9][0-9]{2}|1[0-9]{3}|20[0-3][0-9]|204[0-7])(\.[0-9]+)?|0|-[1-9][0-9]*|-[1-9][0-9]{2,}|-1[0-9]{3}|-20[0-3][0-9]|-204[0-7])$' diff --git a/tests/__snapshots__/small-key-size-c++-snapshot.yml b/tests/__snapshots__/small-key-size-c++-snapshot.yml new file mode 100644 index 00000000..acc012ed --- /dev/null +++ b/tests/__snapshots__/small-key-size-c++-snapshot.yml @@ -0,0 +1,50 @@ +id: small-key-size-c++ +snapshots: + ? | + void foo() { + size_t bad_size = 1024; + size_t good_size = 2048; + DH_generate_parameters_ex(NULL, bad_size); + DSA_generate_parameters_ex(NULL, bad_size); + EVP_PKEY_CTX_set_dh_paramgen_prime_len(NULL, bad_size); + EVP_PKEY_CTX_set_dsa_paramgen_bits(NULL, bad_size); + EVP_PKEY_CTX_set_rsa_keygen_bits(NULL, bad_size); + RSA_generate_key_ex(NULL, bad_size); + RSA_generate_key_fips(NULL, bad_size);} + : labels: + - source: DH_generate_parameters_ex(NULL, bad_size); + style: primary + start: 62 + end: 104 + - source: DH_generate_parameters_ex + style: secondary + start: 62 + end: 87 + - source: bad_size + style: secondary + start: 94 + end: 102 + - source: (NULL, bad_size) + style: secondary + start: 87 + end: 103 + - source: DH_generate_parameters_ex(NULL, bad_size) + style: secondary + start: 62 + end: 103 + - source: bad_size + style: secondary + start: 20 + end: 28 + - source: '1024' + style: secondary + start: 31 + end: 35 + - source: bad_size = 1024 + style: secondary + start: 20 + end: 35 + - source: size_t bad_size = 1024; + style: secondary + start: 13 + end: 36 diff --git a/tests/cpp/small-key-size-cpp-test.yml b/tests/cpp/small-key-size-cpp-test.yml new file mode 100644 index 00000000..0b07fa82 --- /dev/null +++ b/tests/cpp/small-key-size-cpp-test.yml @@ -0,0 +1,26 @@ +id: small-key-size-c++ +valid: + - | + void foo() { + size_t bad_size = 1024; + size_t good_size = 2048; + DH_generate_parameters_ex(NULL, good_size); + DSA_generate_parameters_ex(NULL, good_size); + EVP_PKEY_CTX_set_dh_paramgen_prime_len(NULL, good_size); + EVP_PKEY_CTX_set_dsa_paramgen_bits(NULL, good_size); + EVP_PKEY_CTX_set_rsa_keygen_bits(NULL, good_size); + RSA_generate_key_ex(NULL, good_size); + RSA_generate_key_fips(NULL, good_size);} + +invalid: + - | + void foo() { + size_t bad_size = 1024; + size_t good_size = 2048; + DH_generate_parameters_ex(NULL, bad_size); + DSA_generate_parameters_ex(NULL, bad_size); + EVP_PKEY_CTX_set_dh_paramgen_prime_len(NULL, bad_size); + EVP_PKEY_CTX_set_dsa_paramgen_bits(NULL, bad_size); + EVP_PKEY_CTX_set_rsa_keygen_bits(NULL, bad_size); + RSA_generate_key_ex(NULL, bad_size); + RSA_generate_key_fips(NULL, bad_size);} From a1d5bc5007046594492225a0fa629927be57d12c Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 27 Sep 2024 18:05:41 +0530 Subject: [PATCH 27/41] jwt-python-hardcoded-secret-python --- .../jwt-python-hardcoded-secret-python.yml | 100 ++++++++++++++++++ ...ython-hardcoded-secret-python-snapshot.yml | 40 +++++++ ...wt-python-hardcoded-secret-python-test.yml | 14 +++ 3 files changed, 154 insertions(+) create mode 100644 rules/python/security/jwt-python-hardcoded-secret-python.yml create mode 100644 tests/__snapshots__/jwt-python-hardcoded-secret-python-snapshot.yml create mode 100644 tests/python/jwt-python-hardcoded-secret-python-test.yml diff --git a/rules/python/security/jwt-python-hardcoded-secret-python.yml b/rules/python/security/jwt-python-hardcoded-secret-python.yml new file mode 100644 index 00000000..8015d771 --- /dev/null +++ b/rules/python/security/jwt-python-hardcoded-secret-python.yml @@ -0,0 +1,100 @@ +id: jwt-python-hardcoded-secret-python +severity: warning +language: python +message: >- + Hardcoded JWT secret or private key is used. This is a Insufficiently + Protected Credentials weakness: + https://cwe.mitre.org/data/definitions/522.html Consider using an + appropriate security mechanism to protect the credentials (e.g. keeping + secrets in environment variables). +note: >- + [CWE-522] Insufficiently Protected Credentials. + [REFERENCES] + - https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ +utils: + match_pattern_followed_by_instance: + inside: + stopBy: end + kind: function_definition + has: + stopBy: end + kind: expression_statement + pattern: $C + has: + kind: assignment + has: + kind: call + has: + kind: argument_list + has: + kind: identifier + nthChild: 2 + pattern: $S + + match_pattern_followed_by_instance_name: + inside: + stopBy: end + kind: function_definition + has: + stopBy: end + kind: expression_statement + pattern: $C + has: + kind: assignment + has: + kind: call + has: + kind: attribute + regex: ^jwt.encode + + match_pattern_followed_by_instance_value: + follows: + stopBy: end + kind: expression_statement + has: + stopBy: end + kind: assignment + all: + - has: + stopBy: end + kind: identifier + pattern: $S + - has: + stopBy: end + kind: string + + combined_utils: + all: + - matches: match_pattern_followed_by_instance + - matches: match_pattern_followed_by_instance_value + - matches: match_pattern_followed_by_instance_name + + match_pattern_followed_by_instance_value_one: + has: + kind: assignment + has: + kind: call + has: + kind: argument_list + has: + kind: string + nthChild: 2 + + match_pattern_followed_by_instance_value_two: + has: + kind: assignment + has: + kind: call + has: + kind: attribute + regex: ^jwt.encode + + combined_utils_two: + all: + - matches: match_pattern_followed_by_instance_value_one + - matches: match_pattern_followed_by_instance_value_two +rule: + kind: expression_statement + any: + - matches: combined_utils + - matches: combined_utils_two diff --git a/tests/__snapshots__/jwt-python-hardcoded-secret-python-snapshot.yml b/tests/__snapshots__/jwt-python-hardcoded-secret-python-snapshot.yml new file mode 100644 index 00000000..e8384206 --- /dev/null +++ b/tests/__snapshots__/jwt-python-hardcoded-secret-python-snapshot.yml @@ -0,0 +1,40 @@ +id: jwt-python-hardcoded-secret-python +snapshots: + ? | + encoded = jwt.encode({"some": "payload"}, "secret", algorithm="HS256") + encoded = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS256') + secret = "secret" + encoded = jwt.encode({"some": "payload"}, secret, algorithm="HS256") + : labels: + - source: 'encoded = jwt.encode({"some": "payload"}, "secret", algorithm="HS256")' + style: primary + start: 0 + end: 70 + - source: '"secret"' + style: secondary + start: 42 + end: 50 + - source: '({"some": "payload"}, "secret", algorithm="HS256")' + style: secondary + start: 20 + end: 70 + - source: 'jwt.encode({"some": "payload"}, "secret", algorithm="HS256")' + style: secondary + start: 10 + end: 70 + - source: 'encoded = jwt.encode({"some": "payload"}, "secret", algorithm="HS256")' + style: secondary + start: 0 + end: 70 + - source: jwt.encode + style: secondary + start: 10 + end: 20 + - source: 'jwt.encode({"some": "payload"}, "secret", algorithm="HS256")' + style: secondary + start: 10 + end: 70 + - source: 'encoded = jwt.encode({"some": "payload"}, "secret", algorithm="HS256")' + style: secondary + start: 0 + end: 70 diff --git a/tests/python/jwt-python-hardcoded-secret-python-test.yml b/tests/python/jwt-python-hardcoded-secret-python-test.yml new file mode 100644 index 00000000..226ea37a --- /dev/null +++ b/tests/python/jwt-python-hardcoded-secret-python-test.yml @@ -0,0 +1,14 @@ +id: jwt-python-hardcoded-secret-python +valid: + - | + encoded = jwt.encode({"some": "payload"}, secret_key, algorithm="HS256") + secret_const = 3 + encoded = jwt.encode({"some": "payload"}, secret_const, algorithm="HS256") + return encoded + +invalid: + - | + encoded = jwt.encode({"some": "payload"}, "secret", algorithm="HS256") + encoded = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS256') + secret = "secret" + encoded = jwt.encode({"some": "payload"}, secret, algorithm="HS256") From d5609b32334aafb6d13d79f7a3feed67967001e7 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 27 Sep 2024 18:13:17 +0530 Subject: [PATCH 28/41] Minor Corrections --- .../security/simple-command-injection-direct-input-java.yml | 3 +-- rules/python/security/jwt-python-hardcoded-secret-python.yml | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/rules/java/security/simple-command-injection-direct-input-java.yml b/rules/java/security/simple-command-injection-direct-input-java.yml index ad7f3e6e..592c8724 100644 --- a/rules/java/security/simple-command-injection-direct-input-java.yml +++ b/rules/java/security/simple-command-injection-direct-input-java.yml @@ -9,8 +9,7 @@ message: >- commands with user input. If this is unavoidable, validate and sanitize the input, and use safe methods for executing the commands. For more information, see: [Java command injection - prevention](https://semgrep.dev/docs/cheat-sheets/java-command-injection/\ - )" + prevention]" note: >- [CWE-78] Improper Neutralization of Special Elements used in an OS [REFERENCES] diff --git a/rules/python/security/jwt-python-hardcoded-secret-python.yml b/rules/python/security/jwt-python-hardcoded-secret-python.yml index 8015d771..eae611c3 100644 --- a/rules/python/security/jwt-python-hardcoded-secret-python.yml +++ b/rules/python/security/jwt-python-hardcoded-secret-python.yml @@ -9,8 +9,6 @@ message: >- secrets in environment variables). note: >- [CWE-522] Insufficiently Protected Credentials. - [REFERENCES] - - https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ utils: match_pattern_followed_by_instance: inside: From 4db272525ec71aae563b7b28b0568304c82acbc7 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Tue, 1 Oct 2024 19:12:49 +0530 Subject: [PATCH 29/41] use-of-weak-rsa-key-go --- rules/go/security/use-of-weak-rsa-key-go.yml | 36 +++++++++++++++++++ .../use-of-weak-rsa-key-go-snapshot.yml | 21 +++++++++++ tests/go/use-of-weak-rsa-key-go-test.yml | 7 ++++ 3 files changed, 64 insertions(+) create mode 100644 rules/go/security/use-of-weak-rsa-key-go.yml create mode 100644 tests/__snapshots__/use-of-weak-rsa-key-go-snapshot.yml create mode 100644 tests/go/use-of-weak-rsa-key-go-test.yml diff --git a/rules/go/security/use-of-weak-rsa-key-go.yml b/rules/go/security/use-of-weak-rsa-key-go.yml new file mode 100644 index 00000000..783411a8 --- /dev/null +++ b/rules/go/security/use-of-weak-rsa-key-go.yml @@ -0,0 +1,36 @@ +id: use-of-weak-rsa-key-go +language: go +severity: warning +message: >- + RSA keys should be at least 2048 bits. +note: >- + [CWE-326] Inadequate Encryption Strength. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms +utils: + statement_match_pattern_one: + kind: expression_list + all: + - has: + stopBy: end + kind: selector_expression + pattern: $JWT + - has: + stopBy: end + kind: argument_list + - has: + stopBy: end + kind: int_literal + pattern: $BITS + +rule: + kind: expression_list + any: + - matches: statement_match_pattern_one + +constraints: + JWT: + regex: (rsa.GenerateMultiPrimeKey|rsa.GenerateKey) + + BITS: + regex: '^(-?(0|[1-9][0-9]?|[1-9][0-9]{2}|1[0-9]{3}|20[0-3][0-9]|204[0-7])(\.[0-9]+)?|0|-[1-9][0-9]*|-[1-9][0-9]{2,}|-1[0-9]{3}|-20[0-3][0-9]|-204[0-7])$' diff --git a/tests/__snapshots__/use-of-weak-rsa-key-go-snapshot.yml b/tests/__snapshots__/use-of-weak-rsa-key-go-snapshot.yml new file mode 100644 index 00000000..91aeb283 --- /dev/null +++ b/tests/__snapshots__/use-of-weak-rsa-key-go-snapshot.yml @@ -0,0 +1,21 @@ +id: use-of-weak-rsa-key-go +snapshots: + ? | + pvk, err := rsa.GenerateKey(rand.Reader, 1025) + : labels: + - source: rsa.GenerateKey(rand.Reader, 1025) + style: primary + start: 12 + end: 46 + - source: rsa.GenerateKey + style: secondary + start: 12 + end: 27 + - source: (rand.Reader, 1025) + style: secondary + start: 27 + end: 46 + - source: '1025' + style: secondary + start: 41 + end: 45 diff --git a/tests/go/use-of-weak-rsa-key-go-test.yml b/tests/go/use-of-weak-rsa-key-go-test.yml new file mode 100644 index 00000000..0233aa98 --- /dev/null +++ b/tests/go/use-of-weak-rsa-key-go-test.yml @@ -0,0 +1,7 @@ +id: use-of-weak-rsa-key-go +valid: + - | + rsa.GenerateKey(rand.Reader, 2048) +invalid: + - | + pvk, err := rsa.GenerateKey(rand.Reader, 1025) From a1c20ff0a0a95d37855f7b77c0bda2e0e10fb74a Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Tue, 1 Oct 2024 19:14:27 +0530 Subject: [PATCH 30/41] openssl-cbc-static-iv-php --- .../security/openssl-cbc-static-iv-php.yml | 190 ++++++++++++++++++ .../openssl-cbc-static-iv-php-snapshot.yml | 77 +++++++ tests/php/openssl-cbc-static-iv-php-test.yml | 23 +++ 3 files changed, 290 insertions(+) create mode 100644 rules/php/security/openssl-cbc-static-iv-php.yml create mode 100644 tests/__snapshots__/openssl-cbc-static-iv-php-snapshot.yml create mode 100644 tests/php/openssl-cbc-static-iv-php-test.yml diff --git a/rules/php/security/openssl-cbc-static-iv-php.yml b/rules/php/security/openssl-cbc-static-iv-php.yml new file mode 100644 index 00000000..710d8118 --- /dev/null +++ b/rules/php/security/openssl-cbc-static-iv-php.yml @@ -0,0 +1,190 @@ +id: openssl-cbc-static-iv-php +language: php +severity: warning +message: >- + Static IV used with AES in CBC mode. Static IVs enable chosen-plaintext + attacks against encrypted data. +note: >- + [CWE-329] Generation of Predictable IV with CBC Mode. + [REFERENCES] + - https://csrc.nist.gov/publications/detail/sp/800-38a/final +utils: + Match_pattern_with_prefix_openssl_encrypt: + kind: expression_statement + all: + - has: + stopBy: end + kind: function_call_expression + all: + - has: + stopBy: end + kind: name + regex: (openssl_decrypt|openssl_encrypt) + - has: + stopBy: end + kind: arguments + all: + - has: + stopBy: end + kind: argument + nthChild: 2 + has: + stopBy: end + kind: variable_name + pattern: $R + - has: + stopBy: end + kind: argument + nthChild: 5 + has: + stopBy: end + kind: variable_name + pattern: $T + + - follows: + stopBy: end + kind: expression_statement + has: + stopBy: end + kind: assignment_expression + all: + - has: + stopBy: end + kind: variable_name + pattern: $T + - has: + stopBy: end + kind: encapsed_string + + - follows: + stopBy: end + kind: expression_statement + has: + stopBy: end + kind: assignment_expression + all: + - has: + stopBy: end + kind: variable_name + pattern: $R + - has: + stopBy: end + kind: encapsed_string + regex: "^.*-CBC" + + Match_pattern_with_prefix_openssl_decrypt: + kind: return_statement + all: + - has: + stopBy: end + kind: function_call_expression + regex: (openssl_decrypt|openssl_encrypt) + has: + stopBy: end + kind: arguments + all: + - has: + stopBy: end + kind: argument + nthChild: 2 + has: + stopBy: end + kind: variable_name + pattern: $R + - has: + stopBy: end + kind: argument + nthChild: 5 + has: + stopBy: end + kind: variable_name + pattern: $T + + - follows: + stopBy: end + kind: expression_statement + has: + stopBy: end + kind: assignment_expression + all: + - has: + stopBy: end + kind: variable_name + pattern: $T + - has: + stopBy: end + kind: encapsed_string + + - follows: + stopBy: end + kind: expression_statement + has: + stopBy: end + kind: assignment_expression + all: + - has: + stopBy: end + kind: variable_name + pattern: $R + - has: + stopBy: end + kind: encapsed_string + regex: "^.*-CBC" + + Match_pattern_directly_with_prefix_openssl_encrypt: + kind: expression_statement + all: + - has: + stopBy: end + kind: function_call_expression + all: + - has: + stopBy: end + kind: name + regex: (openssl_decrypt|openssl_encrypt) + - has: + stopBy: end + kind: arguments + all: + - has: + stopBy: end + kind: argument + nthChild: 2 + has: + stopBy: end + kind: encapsed_string + regex: "^.*-CBC" + + - has: + stopBy: end + kind: argument + nthChild: 5 + has: + stopBy: end + kind: variable_name + pattern: $T + + - follows: + stopBy: end + kind: expression_statement + has: + stopBy: end + kind: assignment_expression + all: + - has: + stopBy: end + kind: variable_name + pattern: $T + - has: + stopBy: end + kind: encapsed_string + +rule: + any: + - kind: expression_statement + any: + - matches: Match_pattern_with_prefix_openssl_encrypt + - matches: Match_pattern_directly_with_prefix_openssl_encrypt + - kind: return_statement + any: + - matches: Match_pattern_with_prefix_openssl_decrypt diff --git a/tests/__snapshots__/openssl-cbc-static-iv-php-snapshot.yml b/tests/__snapshots__/openssl-cbc-static-iv-php-snapshot.yml new file mode 100644 index 00000000..321ed335 --- /dev/null +++ b/tests/__snapshots__/openssl-cbc-static-iv-php-snapshot.yml @@ -0,0 +1,77 @@ +id: openssl-cbc-static-iv-php +snapshots: + ? | + Date: Thu, 3 Oct 2024 18:03:34 +0530 Subject: [PATCH 31/41] std-return-data-c --- rules/c/security/std-return-data-c.yml | 113 ++++++++++++++++++ .../std-return-data-c-snapshot.yml | 80 +++++++++++++ tests/c/std-return-data-c-test.yml | 15 +++ 3 files changed, 208 insertions(+) create mode 100644 rules/c/security/std-return-data-c.yml create mode 100644 tests/__snapshots__/std-return-data-c-snapshot.yml create mode 100644 tests/c/std-return-data-c-test.yml diff --git a/rules/c/security/std-return-data-c.yml b/rules/c/security/std-return-data-c.yml new file mode 100644 index 00000000..f5c56572 --- /dev/null +++ b/rules/c/security/std-return-data-c.yml @@ -0,0 +1,113 @@ +id: std-return-data-c +language: c +severity: warning +message: >- + $FUNC` returns a pointer to the memory owned by `$VAR`. This pointer + is invalid after `$VAR` goes out of scope, which can trigger a use after + free. +note: >- + [CWE-416: Use After Free. + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/DCL30-C.+Declare+objects+with+appropriate+storage+durations +utils: + MATCH_RETURN_STATEMENT_WITH_STD: + kind: return_statement + all: + - has: + stopBy: end + kind: call_expression + has: + stopBy: end + kind: field_expression + has: + stopBy: end + kind: identifier + pattern: $R + - follows: + stopBy: end + kind: labeled_statement + all: + - has: + stopBy: end + kind: statement_identifier + regex: ^std + - has: + stopBy: end + kind: expression_statement + has: + stopBy: end + kind: binary_expression + all: + - has: + stopBy: end + kind: binary_expression + all: + - has: + stopBy: end + kind: identifier + regex: (vector|array|deque|forward_list|list|map|multimap|multiset|set|unordered_map|unordered_multimap|unordered_multiset|unordered_set) + - has: + stopBy: end + kind: identifier + - has: + stopBy: end + kind: identifier + pattern: $R + - inside: + stopBy: end + kind: compound_statement + follows: + stopBy: end + kind: pointer_declarator + has: + stopBy: end + kind: function_declarator + all: + - has: + stopBy: end + kind: identifier + regex: ^return.* + - has: + stopBy: end + kind: parameter_list + + MATCH_RETURN_STATEMENT_WITHOUT_STD: + kind: return_statement + all: + - has: + stopBy: end + kind: call_expression + has: + stopBy: end + kind: field_expression + has: + stopBy: end + kind: identifier + pattern: $R + - follows: + stopBy: end + kind: expression_statement + has: + stopBy: end + kind: binary_expression + all: + - has: + stopBy: end + kind: binary_expression + all: + - has: + stopBy: end + kind: identifier + regex: (vector|array|deque|forward_list|list|map|multimap|multiset|set|unordered_map|unordered_multimap|unordered_multiset|unordered_set) + - has: + stopBy: end + kind: identifier + - has: + stopBy: end + kind: identifier + pattern: $R +rule: + kind: return_statement + any: + - matches: MATCH_RETURN_STATEMENT_WITH_STD + - matches: MATCH_RETURN_STATEMENT_WITHOUT_STD diff --git a/tests/__snapshots__/std-return-data-c-snapshot.yml b/tests/__snapshots__/std-return-data-c-snapshot.yml new file mode 100644 index 00000000..48de9a2e --- /dev/null +++ b/tests/__snapshots__/std-return-data-c-snapshot.yml @@ -0,0 +1,80 @@ +id: std-return-data-c +snapshots: + ? | + int *return_vector_data() { + std::vector v; + return v.data(); + } + : labels: + - source: return v.data(); + style: primary + start: 48 + end: 64 + - source: v + style: secondary + start: 55 + end: 56 + - source: v.data + style: secondary + start: 55 + end: 61 + - source: v.data() + style: secondary + start: 55 + end: 63 + - source: std + style: secondary + start: 28 + end: 31 + - source: vector + style: secondary + start: 33 + end: 39 + - source: vector + style: secondary + start: 33 + end: 39 + - source: vector v + style: secondary + start: 33 + end: 46 + - source: vector v; + style: secondary + start: 33 + end: 47 + - source: std::vector v; + style: secondary + start: 28 + end: 47 + - source: return_vector_data + style: secondary + start: 5 + end: 23 + - source: () + style: secondary + start: 23 + end: 25 + - source: return_vector_data() + style: secondary + start: 5 + end: 25 + - source: '*return_vector_data()' + style: secondary + start: 4 + end: 25 + - source: |- + { + std::vector v; + return v.data(); + } + style: secondary + start: 26 + end: 66 diff --git a/tests/c/std-return-data-c-test.yml b/tests/c/std-return-data-c-test.yml new file mode 100644 index 00000000..c46c85fa --- /dev/null +++ b/tests/c/std-return-data-c-test.yml @@ -0,0 +1,15 @@ +id: std-return-data-c +valid: + - | + class Wrapper { + std::vector v; + int *return_vector_begin_iterator() { + return v.data(); + } + } +invalid: + - | + int *return_vector_data() { + std::vector v; + return v.data(); + } From f83aec62a59c54c8fa183caec388c0bfb089ae84 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 3 Oct 2024 18:07:51 +0530 Subject: [PATCH 32/41] node-sequelize-empty-password-argument-javascript --- ...ize-empty-password-argument-javascript.yml | 78 +++++++++++++++++++ ...-password-argument-javascript-snapshot.yml | 61 +++++++++++++++ ...mpty-password-argument-javascript-test.yml | 18 +++++ 3 files changed, 157 insertions(+) create mode 100644 rules/javascript/security/node-sequelize-empty-password-argument-javascript.yml create mode 100644 tests/__snapshots__/node-sequelize-empty-password-argument-javascript-snapshot.yml create mode 100644 tests/javascript/node-sequelize-empty-password-argument-javascript-test.yml diff --git a/rules/javascript/security/node-sequelize-empty-password-argument-javascript.yml b/rules/javascript/security/node-sequelize-empty-password-argument-javascript.yml new file mode 100644 index 00000000..eaabe687 --- /dev/null +++ b/rules/javascript/security/node-sequelize-empty-password-argument-javascript.yml @@ -0,0 +1,78 @@ +id: node-sequelize-empty-password-argument-javascript +language: javascript +severity: warning +message: >- + The application creates a database connection with an empty password. + This can lead to unauthorized access by either an internal or external + malicious actor. To prevent this vulnerability, enforce authentication + when connecting to a database by using environment variables to securely + provide credentials or retrieving them from a secure vault or HSM + (Hardware Security Module). +note: >- + [CWE-287] Improper Authentication. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + MATCH_BLANK_PASSWORD: + kind: string + pattern: $Q + inside: + stopBy: end + kind: lexical_declaration + all: + - has: + stopBy: end + kind: new_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: string + nthChild: 3 + pattern: $Q + not: + has: + stopBy: end + kind: string_fragment + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + has: + stopBy: end + kind: identifier + pattern: $E + - follows: + stopBy: end + kind: import_statement + has: + stopBy: end + kind: import_clause + has: + stopBy: end + kind: identifier + pattern: $E + - follows: + stopBy: end + kind: import_statement + has: + stopBy: end + kind: import_clause + has: + stopBy: end + kind: identifier + pattern: $E + +rule: + kind: string + matches: MATCH_BLANK_PASSWORD diff --git a/tests/__snapshots__/node-sequelize-empty-password-argument-javascript-snapshot.yml b/tests/__snapshots__/node-sequelize-empty-password-argument-javascript-snapshot.yml new file mode 100644 index 00000000..6034344a --- /dev/null +++ b/tests/__snapshots__/node-sequelize-empty-password-argument-javascript-snapshot.yml @@ -0,0 +1,61 @@ +id: node-sequelize-empty-password-argument-javascript +snapshots: + ? | + const Sequelize = require('sequelize'); + const sequelize1 = new Sequelize('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + : labels: + - source: '''''' + style: primary + start: 97 + end: 99 + - source: Sequelize + style: secondary + start: 63 + end: 72 + - source: '''''' + style: secondary + start: 97 + end: 99 + - source: |- + ('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 72 + end: 158 + - source: |- + new Sequelize('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 59 + end: 158 + - source: Sequelize + style: secondary + start: 6 + end: 15 + - source: Sequelize = require('sequelize') + style: secondary + start: 6 + end: 38 + - source: const Sequelize = require('sequelize'); + style: secondary + start: 0 + end: 39 + - source: |- + const sequelize1 = new Sequelize('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 40 + end: 158 diff --git a/tests/javascript/node-sequelize-empty-password-argument-javascript-test.yml b/tests/javascript/node-sequelize-empty-password-argument-javascript-test.yml new file mode 100644 index 00000000..093cf3a7 --- /dev/null +++ b/tests/javascript/node-sequelize-empty-password-argument-javascript-test.yml @@ -0,0 +1,18 @@ +id: node-sequelize-empty-password-argument-javascript +valid: + - | + const Sequelize = require('sequelize'); + const sequelize = new Sequelize({ + database: 'pinche', + username: 'root', + password: '123456789', + dialect: 'mysql' + }); +invalid: + - | + const Sequelize = require('sequelize'); + const sequelize1 = new Sequelize('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) From 6e710c565f1848f06680a57506cecac403f63eea Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 3 Oct 2024 18:09:09 +0530 Subject: [PATCH 33/41] node-sequelize-empty-password-argument-typescript --- ...ize-empty-password-argument-typescript.yml | 78 +++++++++++++++++++ ...-password-argument-typescript-snapshot.yml | 61 +++++++++++++++ ...mpty-password-argument-typescript-test.yml | 18 +++++ 3 files changed, 157 insertions(+) create mode 100644 rules/typescript/security/node-sequelize-empty-password-argument-typescript.yml create mode 100644 tests/__snapshots__/node-sequelize-empty-password-argument-typescript-snapshot.yml create mode 100644 tests/typescript/node-sequelize-empty-password-argument-typescript-test.yml diff --git a/rules/typescript/security/node-sequelize-empty-password-argument-typescript.yml b/rules/typescript/security/node-sequelize-empty-password-argument-typescript.yml new file mode 100644 index 00000000..a5eab9dd --- /dev/null +++ b/rules/typescript/security/node-sequelize-empty-password-argument-typescript.yml @@ -0,0 +1,78 @@ +id: node-sequelize-empty-password-argument-typescript +language: typescript +severity: warning +message: >- + The application creates a database connection with an empty password. + This can lead to unauthorized access by either an internal or external + malicious actor. To prevent this vulnerability, enforce authentication + when connecting to a database by using environment variables to securely + provide credentials or retrieving them from a secure vault or HSM + (Hardware Security Module). +note: >- + [CWE-287] Improper Authentication. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + MATCH_BLANK_PASSWORD: + kind: string + pattern: $Q + inside: + stopBy: end + kind: lexical_declaration + all: + - has: + stopBy: end + kind: new_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: string + nthChild: 3 + pattern: $Q + not: + has: + stopBy: end + kind: string_fragment + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + has: + stopBy: end + kind: identifier + pattern: $E + - follows: + stopBy: end + kind: import_statement + has: + stopBy: end + kind: import_clause + has: + stopBy: end + kind: identifier + pattern: $E + - follows: + stopBy: end + kind: import_statement + has: + stopBy: end + kind: import_clause + has: + stopBy: end + kind: identifier + pattern: $E + +rule: + kind: string + matches: MATCH_BLANK_PASSWORD diff --git a/tests/__snapshots__/node-sequelize-empty-password-argument-typescript-snapshot.yml b/tests/__snapshots__/node-sequelize-empty-password-argument-typescript-snapshot.yml new file mode 100644 index 00000000..9efc0238 --- /dev/null +++ b/tests/__snapshots__/node-sequelize-empty-password-argument-typescript-snapshot.yml @@ -0,0 +1,61 @@ +id: node-sequelize-empty-password-argument-typescript +snapshots: + ? | + const Sequelize = require('sequelize'); + const sequelize1 = new Sequelize('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + : labels: + - source: '''''' + style: primary + start: 97 + end: 99 + - source: Sequelize + style: secondary + start: 63 + end: 72 + - source: '''''' + style: secondary + start: 97 + end: 99 + - source: |- + ('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 72 + end: 158 + - source: |- + new Sequelize('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 59 + end: 158 + - source: Sequelize + style: secondary + start: 6 + end: 15 + - source: Sequelize = require('sequelize') + style: secondary + start: 6 + end: 38 + - source: const Sequelize = require('sequelize'); + style: secondary + start: 0 + end: 39 + - source: |- + const sequelize1 = new Sequelize('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 40 + end: 158 diff --git a/tests/typescript/node-sequelize-empty-password-argument-typescript-test.yml b/tests/typescript/node-sequelize-empty-password-argument-typescript-test.yml new file mode 100644 index 00000000..0c17510d --- /dev/null +++ b/tests/typescript/node-sequelize-empty-password-argument-typescript-test.yml @@ -0,0 +1,18 @@ +id: node-sequelize-empty-password-argument-typescript +valid: + - | + const Sequelize = require('sequelize'); + const sequelize = new Sequelize({ + database: 'pinche', + username: 'root', + password: '123456789', + dialect: 'mysql' + }); +invalid: + - | + const Sequelize = require('sequelize'); + const sequelize1 = new Sequelize('database', 'username', '', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) From 52b258fb8bd8f8ed2b2c963f1e84f9ef3585541d Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 4 Oct 2024 17:53:20 +0530 Subject: [PATCH 34/41] small-key-size-cpp --- rules/cpp/security/small-key-size-cpp.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/cpp/security/small-key-size-cpp.yml b/rules/cpp/security/small-key-size-cpp.yml index 631995ec..94a5bc48 100644 --- a/rules/cpp/security/small-key-size-cpp.yml +++ b/rules/cpp/security/small-key-size-cpp.yml @@ -1,5 +1,5 @@ -id: small-key-size-c++ -language: c +id: small-key-size-cpp +language: cpp severity: warning message: >- $KEY_FUNCTION` is using a key size of only $KEY_BITS bits. This is From e9a1690d0323a2b3a23c2db8339c0707fe5dd7da Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 4 Oct 2024 17:55:31 +0530 Subject: [PATCH 35/41] sizeof-this-cpp --- rules/cpp/security/sizeof-this-cpp.yml | 13 +++++++++++++ tests/__snapshots__/sizeof-this-cpp-snapshot.yml | 9 +++++++++ tests/cpp/sizeof-this-cpp-test.yml | 7 +++++++ 3 files changed, 29 insertions(+) create mode 100644 rules/cpp/security/sizeof-this-cpp.yml create mode 100644 tests/__snapshots__/sizeof-this-cpp-snapshot.yml create mode 100644 tests/cpp/sizeof-this-cpp-test.yml diff --git a/rules/cpp/security/sizeof-this-cpp.yml b/rules/cpp/security/sizeof-this-cpp.yml new file mode 100644 index 00000000..a32bbd6a --- /dev/null +++ b/rules/cpp/security/sizeof-this-cpp.yml @@ -0,0 +1,13 @@ +id: sizeof-this-cpp +language: cpp +severity: warning +message: >- + Do not use `sizeof(this)` to get the number of bytes of the object in + memory. It returns the size of the pointer, not the size of the object. +note: >- + [CWE-467]: Use of sizeof() on a Pointer Type + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/ARR01-C.+Do+not+apply+the+sizeof+operator+to+a+pointer+when+taking+the+size+of+an+array +rule: + any: + - pattern: "sizeof(this)" diff --git a/tests/__snapshots__/sizeof-this-cpp-snapshot.yml b/tests/__snapshots__/sizeof-this-cpp-snapshot.yml new file mode 100644 index 00000000..4d874f00 --- /dev/null +++ b/tests/__snapshots__/sizeof-this-cpp-snapshot.yml @@ -0,0 +1,9 @@ +id: sizeof-this-cpp +snapshots: + ? | + return sizeof(this); + : labels: + - source: sizeof(this) + style: primary + start: 7 + end: 19 diff --git a/tests/cpp/sizeof-this-cpp-test.yml b/tests/cpp/sizeof-this-cpp-test.yml new file mode 100644 index 00000000..343b2a66 --- /dev/null +++ b/tests/cpp/sizeof-this-cpp-test.yml @@ -0,0 +1,7 @@ +id: sizeof-this-cpp +valid: + - | + return sizeof(*this); +invalid: + - | + return sizeof(this); From b2c8b0559aa82b299f5aa2dfce7e48f462e37270 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 4 Oct 2024 17:57:23 +0530 Subject: [PATCH 36/41] std-return-data-c changed --- rules/c/security/std-return-data-c.yml | 30 +++++++--------- .../std-return-data-c-snapshot.yml | 36 +++++++------------ 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/rules/c/security/std-return-data-c.yml b/rules/c/security/std-return-data-c.yml index f5c56572..6f10adff 100644 --- a/rules/c/security/std-return-data-c.yml +++ b/rules/c/security/std-return-data-c.yml @@ -53,23 +53,12 @@ utils: stopBy: end kind: identifier pattern: $R - - inside: - stopBy: end - kind: compound_statement - follows: - stopBy: end - kind: pointer_declarator - has: - stopBy: end - kind: function_declarator - all: - - has: - stopBy: end - kind: identifier - regex: ^return.* - - has: - stopBy: end - kind: parameter_list + inside: + stopBy: end + kind: function_definition + has: + stopBy: end + kind: primitive_type MATCH_RETURN_STATEMENT_WITHOUT_STD: kind: return_statement @@ -106,6 +95,13 @@ utils: stopBy: end kind: identifier pattern: $R + inside: + stopBy: end + kind: function_definition + has: + stopBy: end + kind: primitive_type + rule: kind: return_statement any: diff --git a/tests/__snapshots__/std-return-data-c-snapshot.yml b/tests/__snapshots__/std-return-data-c-snapshot.yml index 48de9a2e..8c6c6885 100644 --- a/tests/__snapshots__/std-return-data-c-snapshot.yml +++ b/tests/__snapshots__/std-return-data-c-snapshot.yml @@ -38,6 +38,18 @@ snapshots: style: secondary start: 33 end: 43 + - source: int + style: secondary + start: 0 + end: 3 + - source: |- + int *return_vector_data() { + std::vector v; + return v.data(); + } + style: secondary + start: 0 + end: 66 - source: v style: secondary start: 45 @@ -54,27 +66,3 @@ snapshots: style: secondary start: 28 end: 47 - - source: return_vector_data - style: secondary - start: 5 - end: 23 - - source: () - style: secondary - start: 23 - end: 25 - - source: return_vector_data() - style: secondary - start: 5 - end: 25 - - source: '*return_vector_data()' - style: secondary - start: 4 - end: 25 - - source: |- - { - std::vector v; - return v.data(); - } - style: secondary - start: 26 - end: 66 From 78143e92492f940f6915957655dd341b67feffb9 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 4 Oct 2024 17:59:25 +0530 Subject: [PATCH 37/41] std-return-data-cpp --- rules/cpp/security/std-return-data-cpp.yml | 124 ++++++++++++++++++ .../std-return-data-cpp-snapshot.yml | 76 +++++++++++ tests/cpp/std-return-data-cpp-test.yml | 15 +++ 3 files changed, 215 insertions(+) create mode 100644 rules/cpp/security/std-return-data-cpp.yml create mode 100644 tests/__snapshots__/std-return-data-cpp-snapshot.yml create mode 100644 tests/cpp/std-return-data-cpp-test.yml diff --git a/rules/cpp/security/std-return-data-cpp.yml b/rules/cpp/security/std-return-data-cpp.yml new file mode 100644 index 00000000..e36e1637 --- /dev/null +++ b/rules/cpp/security/std-return-data-cpp.yml @@ -0,0 +1,124 @@ +id: std-return-data-cpp +language: cpp +severity: warning +message: >- + $FUNC` returns a pointer to the memory owned by `$VAR`. This pointer + is invalid after `$VAR` goes out of scope, which can trigger a use after + free. +note: >- + [CWE-416: Use After Free. + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/DCL30-C.+Declare+objects+with+appropriate+storage+durations +utils: + MATCH_RETURN_STATEMENT_WITH_STD: + kind: return_statement + has: + kind: call_expression + has: + kind: field_expression + has: + kind: identifier + pattern: $VAR + inside: + stopBy: end + kind: return_statement + follows: + stopBy: end + kind: declaration + all: + - has: + stopBy: end + kind: identifier + pattern: $VAR + - has: + stopBy: end + kind: template_type + has: + stopBy: end + kind: type_identifier + regex: (^vector|^array$|^deque$|^forward_list$|^list$|^map$|^multimap$|^multiset$|^set$|^unordered_map$|^unordered_multimap$|^unordered_multiset$|^unordered_set$) + - has: + stopBy: end + kind: qualified_identifier + has: + stopBy: end + kind: namespace_identifier + pattern: $I + inside: + stopBy: end + kind: compound_statement + all: + - follows: + stopBy: end + kind: pointer_declarator + has: + stopBy: end + kind: function_declarator + has: + stopBy: end + kind: identifier + regex: ^return.* + - follows: + stopBy: end + kind: primitive_type + pattern: $J + MATCH_RETURN_STATEMENT_WITHOUT_STD: + kind: return_statement + has: + kind: call_expression + has: + kind: field_expression + has: + kind: identifier + pattern: $VAR + inside: + stopBy: end + kind: return_statement + follows: + stopBy: end + kind: declaration + all: + - has: + stopBy: end + kind: identifier + pattern: $VAR + - has: + stopBy: end + kind: template_type + has: + stopBy: end + kind: type_identifier + regex: (^vector|^array$|^deque$|^forward_list$|^list$|^map$|^multimap$|^multiset$|^set$|^unordered_map$|^unordered_multimap$|^unordered_multiset$|^unordered_set$) + inside: + stopBy: end + kind: compound_statement + all: + - follows: + stopBy: end + kind: pointer_declarator + has: + stopBy: end + kind: function_declarator + all: + - has: + stopBy: end + kind: identifier + regex: ^return.* + - has: + stopBy: end + kind: parameter_list + - follows: + stopBy: end + kind: primitive_type + pattern: $J +rule: + kind: return_statement + any: + - matches: MATCH_RETURN_STATEMENT_WITH_STD + - matches: MATCH_RETURN_STATEMENT_WITHOUT_STD + +constraints: + I: + regex: "^std$" + J: + regex: ^(int|char|float)$ diff --git a/tests/__snapshots__/std-return-data-cpp-snapshot.yml b/tests/__snapshots__/std-return-data-cpp-snapshot.yml new file mode 100644 index 00000000..ad3d8145 --- /dev/null +++ b/tests/__snapshots__/std-return-data-cpp-snapshot.yml @@ -0,0 +1,76 @@ +id: std-return-data-cpp +snapshots: + ? | + int *return_vector_data() { + std::vector v; + return v.data(); + } + : labels: + - source: return v.data(); + style: primary + start: 48 + end: 64 + - source: v + style: secondary + start: 45 + end: 46 + - source: vector + style: secondary + start: 33 + end: 39 + - source: vector + style: secondary + start: 33 + end: 44 + - source: return_vector_data + style: secondary + start: 5 + end: 23 + - source: return_vector_data() + style: secondary + start: 5 + end: 25 + - source: '*return_vector_data()' + style: secondary + start: 4 + end: 25 + - source: int + style: secondary + start: 0 + end: 3 + - source: |- + { + std::vector v; + return v.data(); + } + style: secondary + start: 26 + end: 66 + - source: std + style: secondary + start: 28 + end: 31 + - source: std::vector + style: secondary + start: 28 + end: 44 + - source: std::vector v; + style: secondary + start: 28 + end: 47 + - source: return v.data(); + style: secondary + start: 48 + end: 64 + - source: v + style: secondary + start: 55 + end: 56 + - source: v.data + style: secondary + start: 55 + end: 61 + - source: v.data() + style: secondary + start: 55 + end: 63 diff --git a/tests/cpp/std-return-data-cpp-test.yml b/tests/cpp/std-return-data-cpp-test.yml new file mode 100644 index 00000000..881e0957 --- /dev/null +++ b/tests/cpp/std-return-data-cpp-test.yml @@ -0,0 +1,15 @@ +id: std-return-data-cpp +valid: + - | + class Wrapper { + std::vector v; + int *return_vector_begin_iterator() { + return v.data(); + } + } +invalid: + - | + int *return_vector_data() { + std::vector v; + return v.data(); + } From 381a23e1f688c7b388f6902ef5ef1d0b3851c337 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 4 Oct 2024 18:01:05 +0530 Subject: [PATCH 38/41] small-key-size-cpp id changed --- ...ey-size-c++-snapshot.yml => small-key-size-cpp-snapshot.yml} | 2 +- tests/cpp/small-key-size-cpp-test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/__snapshots__/{small-key-size-c++-snapshot.yml => small-key-size-cpp-snapshot.yml} (98%) diff --git a/tests/__snapshots__/small-key-size-c++-snapshot.yml b/tests/__snapshots__/small-key-size-cpp-snapshot.yml similarity index 98% rename from tests/__snapshots__/small-key-size-c++-snapshot.yml rename to tests/__snapshots__/small-key-size-cpp-snapshot.yml index acc012ed..caee978d 100644 --- a/tests/__snapshots__/small-key-size-c++-snapshot.yml +++ b/tests/__snapshots__/small-key-size-cpp-snapshot.yml @@ -1,4 +1,4 @@ -id: small-key-size-c++ +id: small-key-size-cpp snapshots: ? | void foo() { diff --git a/tests/cpp/small-key-size-cpp-test.yml b/tests/cpp/small-key-size-cpp-test.yml index 0b07fa82..636b0ce3 100644 --- a/tests/cpp/small-key-size-cpp-test.yml +++ b/tests/cpp/small-key-size-cpp-test.yml @@ -1,4 +1,4 @@ -id: small-key-size-c++ +id: small-key-size-cpp valid: - | void foo() { From e00b5fac7dade6694e079ecf31ad564c4026d9f0 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 4 Oct 2024 18:02:52 +0530 Subject: [PATCH 39/41] node-sequelize-hardcoded-secret-argument-javascript --- ...e-hardcoded-secret-argument-javascript.yml | 77 +++++++++++++++++++ ...ed-secret-argument-javascript-snapshot.yml | 65 ++++++++++++++++ ...dcoded-secret-argument-javascript-test.yml | 18 +++++ 3 files changed, 160 insertions(+) create mode 100644 rules/javascript/security/node-sequelize-hardcoded-secret-argument-javascript.yml create mode 100644 tests/__snapshots__/node-sequelize-hardcoded-secret-argument-javascript-snapshot.yml create mode 100644 tests/javascript/node-sequelize-hardcoded-secret-argument-javascript-test.yml diff --git a/rules/javascript/security/node-sequelize-hardcoded-secret-argument-javascript.yml b/rules/javascript/security/node-sequelize-hardcoded-secret-argument-javascript.yml new file mode 100644 index 00000000..ae91bd16 --- /dev/null +++ b/rules/javascript/security/node-sequelize-hardcoded-secret-argument-javascript.yml @@ -0,0 +1,77 @@ +id: node-sequelize-hardcoded-secret-argument-javascript +language: javascript +severity: warning +message: >- + The application creates a database connection with an empty password. + This can lead to unauthorized access by either an internal or external + malicious actor. To prevent this vulnerability, enforce authentication + when connecting to a database by using environment variables to securely + provide credentials or retrieving them from a secure vault or HSM + (Hardware Security Module). +note: >- + [CWE-287] Improper Authentication. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + MATCH_BLANK_PASSWORD: + kind: string + pattern: $Q + inside: + stopBy: end + kind: lexical_declaration + all: + - has: + stopBy: end + kind: new_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: string + nthChild: 3 + pattern: $Q + has: + stopBy: end + kind: string_fragment + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + has: + stopBy: end + kind: identifier + pattern: $E + - follows: + stopBy: end + kind: import_statement + has: + stopBy: end + kind: import_clause + has: + stopBy: end + kind: identifier + pattern: $E + - follows: + stopBy: end + kind: import_statement + has: + stopBy: end + kind: import_clause + has: + stopBy: end + kind: identifier + pattern: $E + +rule: + kind: string + matches: MATCH_BLANK_PASSWORD diff --git a/tests/__snapshots__/node-sequelize-hardcoded-secret-argument-javascript-snapshot.yml b/tests/__snapshots__/node-sequelize-hardcoded-secret-argument-javascript-snapshot.yml new file mode 100644 index 00000000..a9240aff --- /dev/null +++ b/tests/__snapshots__/node-sequelize-hardcoded-secret-argument-javascript-snapshot.yml @@ -0,0 +1,65 @@ +id: node-sequelize-hardcoded-secret-argument-javascript +snapshots: + ? | + const Sequelize = require('sequelize'); + const sequelize = new Sequelize('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + : labels: + - source: '''password''' + style: primary + start: 96 + end: 106 + - source: Sequelize + style: secondary + start: 62 + end: 71 + - source: password + style: secondary + start: 97 + end: 105 + - source: '''password''' + style: secondary + start: 96 + end: 106 + - source: |- + ('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 71 + end: 165 + - source: |- + new Sequelize('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 58 + end: 165 + - source: Sequelize + style: secondary + start: 6 + end: 15 + - source: Sequelize = require('sequelize') + style: secondary + start: 6 + end: 38 + - source: const Sequelize = require('sequelize'); + style: secondary + start: 0 + end: 39 + - source: |- + const sequelize = new Sequelize('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 40 + end: 165 diff --git a/tests/javascript/node-sequelize-hardcoded-secret-argument-javascript-test.yml b/tests/javascript/node-sequelize-hardcoded-secret-argument-javascript-test.yml new file mode 100644 index 00000000..8cc8edeb --- /dev/null +++ b/tests/javascript/node-sequelize-hardcoded-secret-argument-javascript-test.yml @@ -0,0 +1,18 @@ +id: node-sequelize-hardcoded-secret-argument-javascript +valid: + - | + const Sequelize = require('sequelize'); + const sequelize = new Sequelize({ + database: 'pinche', + username: 'root', + password: '123456789', + dialect: 'mysql' + }) +invalid: + - | + const Sequelize = require('sequelize'); + const sequelize = new Sequelize('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) From 93e4125d1cedef7996f9e5fbcc7fbf98cad20188 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 4 Oct 2024 18:03:57 +0530 Subject: [PATCH 40/41] node-sequelize-hardcoded-secret-argument-typescript --- ...e-hardcoded-secret-argument-typescript.yml | 77 +++++++++++++++++++ ...ed-secret-argument-typescript-snapshot.yml | 65 ++++++++++++++++ ...dcoded-secret-argument-typescript-test.yml | 18 +++++ 3 files changed, 160 insertions(+) create mode 100644 rules/typescript/security/node-sequelize-hardcoded-secret-argument-typescript.yml create mode 100644 tests/__snapshots__/node-sequelize-hardcoded-secret-argument-typescript-snapshot.yml create mode 100644 tests/typescript/node-sequelize-hardcoded-secret-argument-typescript-test.yml diff --git a/rules/typescript/security/node-sequelize-hardcoded-secret-argument-typescript.yml b/rules/typescript/security/node-sequelize-hardcoded-secret-argument-typescript.yml new file mode 100644 index 00000000..e4ea19f9 --- /dev/null +++ b/rules/typescript/security/node-sequelize-hardcoded-secret-argument-typescript.yml @@ -0,0 +1,77 @@ +id: node-sequelize-hardcoded-secret-argument-typescript +language: typescript +severity: warning +message: >- + The application creates a database connection with an empty password. + This can lead to unauthorized access by either an internal or external + malicious actor. To prevent this vulnerability, enforce authentication + when connecting to a database by using environment variables to securely + provide credentials or retrieving them from a secure vault or HSM + (Hardware Security Module). +note: >- + [CWE-287] Improper Authentication. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + MATCH_BLANK_PASSWORD: + kind: string + pattern: $Q + inside: + stopBy: end + kind: lexical_declaration + all: + - has: + stopBy: end + kind: new_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: string + nthChild: 3 + pattern: $Q + has: + stopBy: end + kind: string_fragment + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + has: + stopBy: end + kind: identifier + pattern: $E + - follows: + stopBy: end + kind: import_statement + has: + stopBy: end + kind: import_clause + has: + stopBy: end + kind: identifier + pattern: $E + - follows: + stopBy: end + kind: import_statement + has: + stopBy: end + kind: import_clause + has: + stopBy: end + kind: identifier + pattern: $E + +rule: + kind: string + matches: MATCH_BLANK_PASSWORD diff --git a/tests/__snapshots__/node-sequelize-hardcoded-secret-argument-typescript-snapshot.yml b/tests/__snapshots__/node-sequelize-hardcoded-secret-argument-typescript-snapshot.yml new file mode 100644 index 00000000..1ce5b449 --- /dev/null +++ b/tests/__snapshots__/node-sequelize-hardcoded-secret-argument-typescript-snapshot.yml @@ -0,0 +1,65 @@ +id: node-sequelize-hardcoded-secret-argument-typescript +snapshots: + ? | + const Sequelize = require('sequelize'); + const sequelize = new Sequelize('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + : labels: + - source: '''password''' + style: primary + start: 96 + end: 106 + - source: Sequelize + style: secondary + start: 62 + end: 71 + - source: password + style: secondary + start: 97 + end: 105 + - source: '''password''' + style: secondary + start: 96 + end: 106 + - source: |- + ('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 71 + end: 165 + - source: |- + new Sequelize('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 58 + end: 165 + - source: Sequelize + style: secondary + start: 6 + end: 15 + - source: Sequelize = require('sequelize') + style: secondary + start: 6 + end: 38 + - source: const Sequelize = require('sequelize'); + style: secondary + start: 0 + end: 39 + - source: |- + const sequelize = new Sequelize('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) + style: secondary + start: 40 + end: 165 diff --git a/tests/typescript/node-sequelize-hardcoded-secret-argument-typescript-test.yml b/tests/typescript/node-sequelize-hardcoded-secret-argument-typescript-test.yml new file mode 100644 index 00000000..b45d2743 --- /dev/null +++ b/tests/typescript/node-sequelize-hardcoded-secret-argument-typescript-test.yml @@ -0,0 +1,18 @@ +id: node-sequelize-hardcoded-secret-argument-typescript +valid: + - | + const Sequelize = require('sequelize'); + const sequelize = new Sequelize({ + database: 'pinche', + username: 'root', + password: '123456789', + dialect: 'mysql' + }) +invalid: + - | + const Sequelize = require('sequelize'); + const sequelize = new Sequelize('database', 'username', 'password', { + host: 'localhost', + port: '5433', + dialect: 'postgres' + }) From aeccebcd2fdf2da7eaeb38146b55603563744b8a Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Fri, 4 Oct 2024 18:06:25 +0530 Subject: [PATCH 41/41] return-c-str-cpp --- rules/cpp/security/return-c-str-cpp.yml | 109 +++++++++++++++ .../return-c-str-cpp-snapshot.yml | 130 ++++++++++++++++++ tests/cpp/return-c-str-cpp-test.yml | 63 +++++++++ 3 files changed, 302 insertions(+) create mode 100644 rules/cpp/security/return-c-str-cpp.yml create mode 100644 tests/__snapshots__/return-c-str-cpp-snapshot.yml create mode 100644 tests/cpp/return-c-str-cpp-test.yml diff --git a/rules/cpp/security/return-c-str-cpp.yml b/rules/cpp/security/return-c-str-cpp.yml new file mode 100644 index 00000000..59bcae84 --- /dev/null +++ b/rules/cpp/security/return-c-str-cpp.yml @@ -0,0 +1,109 @@ +id: return-c-str-cpp +language: cpp +severity: warning +message: >- + "`$FUNC` returns a pointer to the memory owned by `$STR`. This pointer + is invalid after `$STR` goes out of scope, which can trigger a use after + free." +note: >- + [CWE-416] Use After Free + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/DCL30-C.+Declare+objects+with+appropriate+storage+durations + - https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP54-CPP.+Do+not+access+an+object+outside+of+its+lifetime + +utils: + util_for_declaration_inside_function: + kind: return_statement + pattern: return $STR.$METHOD(); + follows: + kind: declaration + stopBy: end + any: + - pattern: string $STR; + - pattern: wstring $STR; + - pattern: basic_string $STR; + - pattern: std::string $STR; + - pattern: std::wstring $STR; + - pattern: std::basic_string<$TYPE> $STR; + + util_for_assignment_inside_function: + kind: return_statement + pattern: return $STR.$METHOD(); + follows: + kind: declaration + stopBy: end + any: + - pattern: string $STR = string($STRING); + - pattern: wstring $STR = wstring($STRING); + - pattern: basic_string<$TYPE> $STR = basic_string<$TYPE>($STRING); + - pattern: std::string $STR = std::string($STRING); + - pattern: std::wstring $STR = std::wstring($STRING); + - pattern: std::basic_string<$TYPE> $STR = std::basic_string<$TYPE>($STRING); + + util_for_func_params: + kind: return_statement + pattern: return $STR.$METHOD(); + inside: + stopBy: end + kind: function_definition + has: + stopBy: end + kind: parameter_list + has: + stopBy: end + kind: parameter_declaration + has: + stopBy: end + kind: identifier + field: declarator + pattern: $STR + any: + - has: + any: + - kind: type_identifier + pattern: $IDENTIFIFER + - kind: qualified_identifier + any: + - all: + - has: + kind: namespace_identifier + pattern: $NAMESPACE_IDEN + - has: + kind: template_type + all: + - has: + kind: type_identifier + field: name + pattern: $BASIC_STR + precedes: + kind: template_argument_list + - pattern: $IDENTIFIFER + - kind: template_type + has: + kind: type_identifier + field: name + pattern: $BASIC_STR + precedes: + kind: template_argument_list + +rule: + any: + - matches: util_for_declaration_inside_function + - matches: util_for_assignment_inside_function + - matches: util_for_func_params + - pattern: return basic_string<$TYPE>($$$).$METHOD(); + - pattern: return std::basic_string<$TYPE>($$$).$METHOD(); + - pattern: return string($$$).$METHOD(); + - pattern: return std::string($$$).$METHOD(); + - pattern: return wstring($$$).$METHOD(); + - pattern: return std::wstring($$$).$METHOD(); + +constraints: + METHOD: + regex: ^(c_str|data)$ + IDENTIFIFER: + regex: ^(string|wstring|std::string|std::wstring)$ + BASIC_STR: + regex: ^(basic_string)$ + NAMESPACE_IDEN: + regex: ^(std)$ diff --git a/tests/__snapshots__/return-c-str-cpp-snapshot.yml b/tests/__snapshots__/return-c-str-cpp-snapshot.yml new file mode 100644 index 00000000..063981c6 --- /dev/null +++ b/tests/__snapshots__/return-c-str-cpp-snapshot.yml @@ -0,0 +1,130 @@ +id: return-c-str-cpp +snapshots: + ? | + char *f() { + std::string s = std::string("foo"); + return s.c_str(); + } + : labels: + - source: return s.c_str(); + style: primary + start: 52 + end: 69 + - source: std::string s = std::string("foo"); + style: secondary + start: 14 + end: 49 + ? | + char *f() { + std::string s; + return s.c_str(); + } + : labels: + - source: return s.c_str(); + style: primary + start: 31 + end: 48 + - source: std::string s; + style: secondary + start: 14 + end: 28 + ? | + char *f(std::string s) { + return s.c_str(); + } + : labels: + - source: return s.c_str(); + style: primary + start: 27 + end: 44 + - source: std::string + style: secondary + start: 8 + end: 19 + - source: s + style: secondary + start: 20 + end: 21 + - source: std::string s + style: secondary + start: 8 + end: 21 + - source: (std::string s) + style: secondary + start: 7 + end: 22 + - source: |- + char *f(std::string s) { + return s.c_str(); + } + style: secondary + start: 0 + end: 46 + ? | + char *return_basic_string_directly() { + return std::basic_string("foo").c_str(); + } + : labels: + - source: return std::basic_string("foo").c_str(); + style: primary + start: 41 + end: 87 + ? | + char *return_data_directly() { + return std::string("foo").data(); + } + : labels: + - source: return std::string("foo").data(); + style: primary + start: 33 + end: 66 + ? | + char *return_directly() { + return string("foo").c_str(); + } + : labels: + - source: return string("foo").c_str(); + style: primary + start: 28 + end: 57 + ? | + char *return_namespace_directly() { + return std::string("foo").c_str(); + } + : labels: + - source: return std::string("foo").c_str(); + style: primary + start: 38 + end: 72 + ? | + class Foo { + char *f() { + std::string s = std::string("foo"); + return s.c_str(); + } + }; + : labels: + - source: return s.c_str(); + style: primary + start: 70 + end: 87 + - source: std::string s = std::string("foo"); + style: secondary + start: 30 + end: 65 + ? | + class Foo { + char *f() { + std::string s; + return s.c_str(); + } + }; + : labels: + - source: return s.c_str(); + style: primary + start: 49 + end: 66 + - source: std::string s; + style: secondary + start: 30 + end: 44 diff --git a/tests/cpp/return-c-str-cpp-test.yml b/tests/cpp/return-c-str-cpp-test.yml new file mode 100644 index 00000000..b9ac5f52 --- /dev/null +++ b/tests/cpp/return-c-str-cpp-test.yml @@ -0,0 +1,63 @@ +id: return-c-str-cpp +valid: + - | + std::string return_directly() { + // ok: return-c-str + return std::string("foo"); + } + - | + char *f() { + static std::string s; + // ok: return-c-str + return s.c_str(); + } + - | + char *f() { + std::string s1; + return s.c_str(); + } +invalid: + - | + char *f() { + std::string s; + return s.c_str(); + } + - | + char *f() { + std::string s = std::string("foo"); + return s.c_str(); + } + - | + char *f(std::string s) { + return s.c_str(); + } + - | + class Foo { + char *f() { + std::string s = std::string("foo"); + return s.c_str(); + } + }; + - | + class Foo { + char *f() { + std::string s; + return s.c_str(); + } + }; + - | + char *return_namespace_directly() { + return std::string("foo").c_str(); + } + - | + char *return_directly() { + return string("foo").c_str(); + } + - | + char *return_basic_string_directly() { + return std::basic_string("foo").c_str(); + } + - | + char *return_data_directly() { + return std::string("foo").data(); + }