From c272c2d6bf2cf1cf5c68d6e6f6ba2aab9aabc429 Mon Sep 17 00:00:00 2001 From: Philip Hayton Date: Thu, 22 Feb 2024 13:42:08 +0000 Subject: [PATCH] ci(java): migrate to annotations (#305) --- .../__snapshots__/test.js.snap | 44 -- .../lang/cookie_missing_http_only/test.js | 47 +- .../testdata/bad.java | 1 + .../__snapshots__/test.js.snap | 44 -- tests/java/lang/cookie_missing_secure/test.js | 46 +- .../cookie_missing_secure/testdata/bad.java | 1 + .../__snapshots__/test.js.snap | 44 -- .../java/lang/file_permission_others/test.js | 31 +- .../testdata/others.java | 1 + .../__snapshots__/test.js.snap | 46 -- .../lang/hardcoded_database_password/test.js | 43 +- .../testdata/bad.java | 1 + .../__snapshots__/test.js.snap | 112 ----- .../java/lang/http_response_splitting/test.js | 47 +- .../http_response_splitting/testdata/bad.java | 3 + .../__snapshots__/test.js.snap | 44 -- tests/java/lang/information_leakage/test.js | 31 +- .../information_leakage/testdata/leak.java | 1 + .../__snapshots__/test.js.snap | 80 ---- tests/java/lang/insecure_cookie/test.js | 43 +- .../lang/insecure_cookie/testdata/bad.java | 2 + .../__snapshots__/test.js.snap | 214 --------- .../lang/insufficiently_random_values/test.js | 31 +- .../testdata/bad.java | 6 + .../ldap_injection/__snapshots__/test.js.snap | 42 -- tests/java/lang/ldap_injection/test.js | 19 +- .../testdata/ldap_injection.java | 1 + .../log_injection/__snapshots__/test.js.snap | 110 ----- tests/java/lang/log_injection/test.js | 34 +- .../log_injection/testdata/log_injection.java | 3 + .../lang/logger/__snapshots__/test.js.snap | 50 --- tests/java/lang/logger/test.js | 19 +- tests/java/lang/logger/testdata/simple.java | 1 + .../__snapshots__/test.js.snap | 44 -- .../missing_database_authentication/test.js | 31 +- .../testdata/bad.java | 1 + .../__snapshots__/test.js.snap | 44 -- .../java/lang/missing_integrity_check/test.js | 31 +- .../testdata/missing_integrity_check.java | 1 + .../__snapshots__/test.js.snap | 146 ------ tests/java/lang/os_command_injection/test.js | 31 +- .../os_command_injection/testdata/bad.java | 4 + .../__snapshots__/test.js.snap | 46 -- .../test.js | 43 +- .../testdata/block_cipher.java | 1 + .../rsa_no_padding/__snapshots__/test.js.snap | 44 -- tests/java/lang/rsa_no_padding/test.js | 31 +- .../testdata/bad_no_padding.java | 1 + .../java/lang/sqli/__snapshots__/test.js.snap | 214 --------- tests/java/lang/sqli/test.js | 31 +- tests/java/lang/sqli/testdata/bad.java | 6 + .../__snapshots__/test.js.snap | 418 ------------------ .../lang/trust_boundary_violation/test.js | 31 +- .../testdata/bad.java | 12 + .../weak_hash_md5/__snapshots__/test.js.snap | 86 ---- tests/java/lang/weak_hash_md5/test.js | 19 +- .../lang/weak_hash_md5/testdata/md5_hash.java | 2 + .../weak_hash_sha1/__snapshots__/test.js.snap | 44 -- tests/java/lang/weak_hash_sha1/test.js | 31 +- .../weak_hash_sha1/testdata/sha1_hash.java | 1 + .../__snapshots__/test.js.snap | 52 --- .../java/lang/weak_password_hash_md5/test.js | 31 +- .../testdata/md5_hash.java | 1 + .../__snapshots__/test.js.snap | 52 --- .../java/lang/weak_password_hash_sha1/test.js | 31 +- .../testdata/sha1_hash.java | 1 + .../__snapshots__/test.js.snap | 76 ---- tests/java/lang/xpath_injection/test.js | 19 +- .../testdata/xpath_injection.java | 2 + .../__snapshots__/test.js.snap | 44 -- tests/java/lang/xss_response_writer/test.js | 31 +- .../testdata/vulnerable.java | 1 + .../spring/sqli/__snapshots__/test.js.snap | 146 ------ tests/java/spring/sqli/test.js | 31 +- tests/java/spring/sqli/testdata/bad.java | 4 + 75 files changed, 598 insertions(+), 2560 deletions(-) delete mode 100644 tests/java/lang/cookie_missing_http_only/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/cookie_missing_secure/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/file_permission_others/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/hardcoded_database_password/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/http_response_splitting/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/information_leakage/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/insecure_cookie/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/insufficiently_random_values/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/ldap_injection/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/log_injection/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/logger/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/missing_database_authentication/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/missing_integrity_check/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/os_command_injection/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/padding_oracle_encryption_vulnerability/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/rsa_no_padding/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/sqli/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/trust_boundary_violation/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/weak_hash_md5/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/weak_hash_sha1/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/weak_password_hash_md5/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/weak_password_hash_sha1/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/xpath_injection/__snapshots__/test.js.snap delete mode 100644 tests/java/lang/xss_response_writer/__snapshots__/test.js.snap delete mode 100644 tests/java/spring/sqli/__snapshots__/test.js.snap diff --git a/tests/java/lang/cookie_missing_http_only/__snapshots__/test.js.snap b/tests/java/lang/cookie_missing_http_only/__snapshots__/test.js.snap deleted file mode 100644 index c830e107a..000000000 --- a/tests/java/lang/cookie_missing_http_only/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_cookie_missing_http_only bad 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "1004" - ], - "id": "java_lang_cookie_missing_http_only", - "title": "Missing 'HttpOnly' flag in cookie configuration", - "description": "## Description\\n\\nThe \\"HttpOnly\\" attribute when set to \\"true\\" protects the cookie value from\\nbeing accessed by client side JavaScript such as reading the \\"document.cookie\\"\\nvalues. By enabling this protection, a website that is vulnerable to Cross-Site\\nScripting (XSS) will be able to block malicious scripts from accessing the\\ncookie value from JavaScript.\\n\\n## Remediations\\n\\n✅ Set \`setHttpOnly\` to \`true\`\\n\\n\`\`\`java\\ncookie.setHttpOnly(true);\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_cookie_missing_http_only", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 6, - "end": 6, - "column": { - "start": 21, - "end": 57 - } - }, - "sink": { - "start": 6, - "end": 6, - "column": { - "start": 21, - "end": 57 - }, - "content": "new Cookie(COOKIE_NAME, cookieValue)" - }, - "parent_line_number": 6, - "snippet": "new Cookie(COOKIE_NAME, cookieValue)", - "fingerprint": "f19844cb5814cfe006b0bb91a5260c9c_0", - "old_fingerprint": "72fe7bec9a96db8401a76c1ebfde1d0a_0", - "code_extract": " Cookie cookie = new Cookie(COOKIE_NAME, cookieValue);" - } - ] -}" -`; - -exports[`java_lang_cookie_missing_http_only ok 1`] = `"{}"`; diff --git a/tests/java/lang/cookie_missing_http_only/test.js b/tests/java/lang/cookie_missing_http_only/test.js index 2354db5ab..9b054bb01 100644 --- a/tests/java/lang/cookie_missing_http_only/test.js +++ b/tests/java/lang/cookie_missing_http_only/test.js @@ -1,29 +1,40 @@ -const { createInvoker, createNewInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase); + const invoke = createNewInvoker(ruleId, ruleFile, testBase) - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + + test("bad", () => { + const testCase = "bad.java" + const results = invoke(testCase) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - // new invoker - const invokeV2 = createNewInvoker(ruleId, ruleFile, testBase) + test("main", () => { + const testCase = "main.java" - test("missing_http_only", () => { - const testCase = "main.java" + const results = invoke(testCase) - const results = invokeV2(testCase) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - expect(results.Missing).toEqual([]) - expect(results.Extra).toEqual([]) - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + }) \ No newline at end of file diff --git a/tests/java/lang/cookie_missing_http_only/testdata/bad.java b/tests/java/lang/cookie_missing_http_only/testdata/bad.java index 475f05403..869b8128f 100644 --- a/tests/java/lang/cookie_missing_http_only/testdata/bad.java +++ b/tests/java/lang/cookie_missing_http_only/testdata/bad.java @@ -3,6 +3,7 @@ public class Test { public void cookie() { +// bearer:expected java_lang_cookie_missing_http_only Cookie cookie = new Cookie(COOKIE_NAME, cookieValue); cookie.setPath("/WebGoat"); response.addCookie(cookie); diff --git a/tests/java/lang/cookie_missing_secure/__snapshots__/test.js.snap b/tests/java/lang/cookie_missing_secure/__snapshots__/test.js.snap deleted file mode 100644 index bd3e41160..000000000 --- a/tests/java/lang/cookie_missing_secure/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_cookie_missing_secure bad 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "614" - ], - "id": "java_lang_cookie_missing_secure", - "title": "Missing 'Secure' attribute in cookie configuration", - "description": "## Description\\n\\nThe \\"Secure\\" attribute when set to \\"true\\" ensures that a client will only send\\nthe cookie to the server when HTTPS is being used. This prevents the cookie\\nfrom being observed by unauthorized third parties.\\n\\n## Remediations\\n\\n✅ Set \`setSecure\` to \`true\`\\n\\n\`\`\`java\\ncookie.setSecure(true);\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_cookie_missing_secure", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 6, - "end": 6, - "column": { - "start": 21, - "end": 57 - } - }, - "sink": { - "start": 6, - "end": 6, - "column": { - "start": 21, - "end": 57 - }, - "content": "new Cookie(COOKIE_NAME, cookieValue)" - }, - "parent_line_number": 6, - "snippet": "new Cookie(COOKIE_NAME, cookieValue)", - "fingerprint": "c4bc05c07b10e54f98f66405ee9722e7_0", - "old_fingerprint": "b08f7460785779d809c152233cf5afdf_0", - "code_extract": " Cookie cookie = new Cookie(COOKIE_NAME, cookieValue);" - } - ] -}" -`; - -exports[`java_lang_cookie_missing_secure ok 1`] = `"{}"`; diff --git a/tests/java/lang/cookie_missing_secure/test.js b/tests/java/lang/cookie_missing_secure/test.js index 45b67d516..9b054bb01 100644 --- a/tests/java/lang/cookie_missing_secure/test.js +++ b/tests/java/lang/cookie_missing_secure/test.js @@ -1,30 +1,40 @@ -const { createInvoker, createNewInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.java" - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + const results = invoke(testCase) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("main", () => { + const testCase = "main.java" - // new invoker - const invokeV2 = createNewInvoker(ruleId, ruleFile, testBase) + const results = invoke(testCase) - test("missing_http_only", () => { - const testCase = "main.java" + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - const results = invokeV2(testCase) + test("ok", () => { + const testCase = "ok.java" - expect(results.Missing).toEqual([]) - expect(results.Extra).toEqual([]) - }) + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + }) \ No newline at end of file diff --git a/tests/java/lang/cookie_missing_secure/testdata/bad.java b/tests/java/lang/cookie_missing_secure/testdata/bad.java index 475f05403..fc160c486 100644 --- a/tests/java/lang/cookie_missing_secure/testdata/bad.java +++ b/tests/java/lang/cookie_missing_secure/testdata/bad.java @@ -3,6 +3,7 @@ public class Test { public void cookie() { +// bearer:expected java_lang_cookie_missing_secure Cookie cookie = new Cookie(COOKIE_NAME, cookieValue); cookie.setPath("/WebGoat"); response.addCookie(cookie); diff --git a/tests/java/lang/file_permission_others/__snapshots__/test.js.snap b/tests/java/lang/file_permission_others/__snapshots__/test.js.snap deleted file mode 100644 index ea0f437ec..000000000 --- a/tests/java/lang/file_permission_others/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_file_permission_others ok 1`] = `"{}"`; - -exports[`java_lang_file_permission_others others 1`] = ` -"{ - "warning": [ - { - "cwe_ids": [ - "732" - ], - "id": "java_lang_file_permission_others", - "title": "Permissive file group 'other' ", - "description": "## Description\\n\\nHaving overly permissive file permissions, such as extending read, write, or execute privileges to 'other', is risky and could lead to accidental exposure of sensitive information.\\n\\n## Remediations\\n\\n✅ Keep file permissions as restrictive as possible. With the Posix enum, for example, prefer 'groups' to 'other', when extending privileges to users without owner privileges.\\n\\n\`\`\`java\\n permissions.add(PosixFilePermission.GROUP_WRITE)\\n\`\`\`\\n\\n## Resources\\n- [Java Files class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/nio/file/Files.html)\\n- [Java PosixFilePermission enum](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/nio/file/attribute/PosixFilePermission.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_file_permission_others", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/others.java", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 3, - "end": 51 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 3, - "end": 51 - }, - "content": "permissions.add(PosixFilePermission.OTHER_WRITE)" - }, - "parent_line_number": 3, - "snippet": "permissions.add(PosixFilePermission.OTHER_WRITE)", - "fingerprint": "12e9ca5557a4ca260d8f219fc77d4d18_0", - "old_fingerprint": "c338dacd7a46dcb729fd2bd27f4328e9_0", - "code_extract": " permissions.add(PosixFilePermission.OTHER_WRITE);" - } - ] -}" -`; diff --git a/tests/java/lang/file_permission_others/test.js b/tests/java/lang/file_permission_others/test.js index 56b4e6559..00f4167bc 100644 --- a/tests/java/lang/file_permission_others/test.js +++ b/tests/java/lang/file_permission_others/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("others", () => { - const testCase = "others.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("others", () => { + const testCase = "others.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/file_permission_others/testdata/others.java b/tests/java/lang/file_permission_others/testdata/others.java index 10863c4cb..579527792 100644 --- a/tests/java/lang/file_permission_others/testdata/others.java +++ b/tests/java/lang/file_permission_others/testdata/others.java @@ -1,5 +1,6 @@ public void addOtherPermission(final Path helm) throws IOException { permissions = Files.getPosixFilePermissions(helm); +// bearer:expected java_lang_file_permission_others permissions.add(PosixFilePermission.OTHER_WRITE); Files.setPosixFilePermissions(helm, permissions); diff --git a/tests/java/lang/hardcoded_database_password/__snapshots__/test.js.snap b/tests/java/lang/hardcoded_database_password/__snapshots__/test.js.snap deleted file mode 100644 index c08a131b3..000000000 --- a/tests/java/lang/hardcoded_database_password/__snapshots__/test.js.snap +++ /dev/null @@ -1,46 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_hardcoded_database_password asterisk_case 1`] = `"{}"`; - -exports[`java_lang_hardcoded_database_password bad 1`] = ` -"{ - "warning": [ - { - "cwe_ids": [ - "259" - ], - "id": "java_lang_hardcoded_database_password", - "title": "Usage of hard-coded database password", - "description": "## Description\\n\\nHardcoded password used in database connection string detected. Code is not a safe place to store passwords like this; use environment variables or a key-management system instead.\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_hardcoded_database_password", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 8, - "end": 8, - "column": { - "start": 23, - "end": 73 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 23, - "end": 73 - }, - "content": "DriverManager.getConnection(url, \\"admin\\", \\"admin\\")" - }, - "parent_line_number": 8, - "snippet": "DriverManager.getConnection(url, \\"admin\\", \\"admin\\")", - "fingerprint": "7a00c02c6f0e9c523225383da4ade342_0", - "old_fingerprint": "afb409af8b801ce44ef647d12c7ec368_0", - "code_extract": " Connection conn = DriverManager.getConnection(url, \\"admin\\", \\"admin\\");" - } - ] -}" -`; - -exports[`java_lang_hardcoded_database_password ok 1`] = `"{}"`; diff --git a/tests/java/lang/hardcoded_database_password/test.js b/tests/java/lang/hardcoded_database_password/test.js index 38180e574..9614363e3 100644 --- a/tests/java/lang/hardcoded_database_password/test.js +++ b/tests/java/lang/hardcoded_database_password/test.js @@ -1,25 +1,40 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("asterisk_case", () => { + const testCase = "asterisk_case.java" + + const results = invoke(testCase) - test("asterisk_case", () => { - const testCase = "asterisk_case.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("bad", () => { + const testCase = "bad.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/hardcoded_database_password/testdata/bad.java b/tests/java/lang/hardcoded_database_password/testdata/bad.java index 432da2ebd..9e5ed2f04 100644 --- a/tests/java/lang/hardcoded_database_password/testdata/bad.java +++ b/tests/java/lang/hardcoded_database_password/testdata/bad.java @@ -5,6 +5,7 @@ public class Foo { public static void main() { String url = "jdbc:mysql://localhost:3306/foo"; +// bearer:expected java_lang_hardcoded_database_password Connection conn = DriverManager.getConnection(url, "admin", "admin"); } } \ No newline at end of file diff --git a/tests/java/lang/http_response_splitting/__snapshots__/test.js.snap b/tests/java/lang/http_response_splitting/__snapshots__/test.js.snap deleted file mode 100644 index ae390f967..000000000 --- a/tests/java/lang/http_response_splitting/__snapshots__/test.js.snap +++ /dev/null @@ -1,112 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_http_response_splitting bad 1`] = ` -"{ - "warning": [ - { - "cwe_ids": [ - "79" - ], - "id": "java_lang_http_response_splitting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\n\\nIncluding unsanitized user input in a HTTP response allows an attacker to\\nsplit the response by injecting CRLF characters. An entirely\\nattacker-controlled response can then be returned, creating a cross-site\\nscripting (XSS) vulnerability.\\n\\n## Remediations\\n\\n✅ Avoid using user input in cookies or other headers\\n\\n✅ Remove CRLF sequences from user input:\\n\\n\`\`\`java\\nvar input = request.getParameter(\\"data\\");\\nvar sanitized = input.replaceAll(\\"\\\\r\\\\n\\", \\"\\");\\ncookie.setValue(sanitized);\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_http_response_splitting", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 5, - "end": 28 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 5, - "end": 28 - }, - "content": "new Cookie(\\"oops\\", foo)" - }, - "parent_line_number": 4, - "snippet": "new Cookie(\\"oops\\", foo)", - "fingerprint": "e717435722185b758fde0b9e5e989023_0", - "old_fingerprint": "e877612fdf26a2fdb5bff3098e9989db_0", - "code_extract": " new Cookie(\\"oops\\", foo);" - }, - { - "cwe_ids": [ - "79" - ], - "id": "java_lang_http_response_splitting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\n\\nIncluding unsanitized user input in a HTTP response allows an attacker to\\nsplit the response by injecting CRLF characters. An entirely\\nattacker-controlled response can then be returned, creating a cross-site\\nscripting (XSS) vulnerability.\\n\\n## Remediations\\n\\n✅ Avoid using user input in cookies or other headers\\n\\n✅ Remove CRLF sequences from user input:\\n\\n\`\`\`java\\nvar input = request.getParameter(\\"data\\");\\nvar sanitized = input.replaceAll(\\"\\\\r\\\\n\\", \\"\\");\\ncookie.setValue(sanitized);\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_http_response_splitting", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 8, - "end": 8, - "column": { - "start": 5, - "end": 20 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 5, - "end": 20 - }, - "content": "c.setValue(bar)" - }, - "parent_line_number": 8, - "snippet": "c.setValue(bar)", - "fingerprint": "e717435722185b758fde0b9e5e989023_1", - "old_fingerprint": "e877612fdf26a2fdb5bff3098e9989db_1", - "code_extract": " c.setValue(bar);" - }, - { - "cwe_ids": [ - "79" - ], - "id": "java_lang_http_response_splitting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\n\\nIncluding unsanitized user input in a HTTP response allows an attacker to\\nsplit the response by injecting CRLF characters. An entirely\\nattacker-controlled response can then be returned, creating a cross-site\\nscripting (XSS) vulnerability.\\n\\n## Remediations\\n\\n✅ Avoid using user input in cookies or other headers\\n\\n✅ Remove CRLF sequences from user input:\\n\\n\`\`\`java\\nvar input = request.getParameter(\\"data\\");\\nvar sanitized = input.replaceAll(\\"\\\\r\\\\n\\", \\"\\");\\ncookie.setValue(sanitized);\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_http_response_splitting", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 5, - "end": 60 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 5, - "end": 60 - }, - "content": "new Cookie(\\"oops3\\", foo.replaceAll(\\"\\\\r\\\\n\\", \\"oops\\\\r\\\\n\\"))" - }, - "parent_line_number": 10, - "snippet": "new Cookie(\\"oops3\\", foo.replaceAll(\\"\\\\r\\\\n\\", \\"oops\\\\r\\\\n\\"))", - "fingerprint": "e717435722185b758fde0b9e5e989023_2", - "old_fingerprint": "e877612fdf26a2fdb5bff3098e9989db_2", - "code_extract": " new Cookie(\\"oops3\\", foo.replaceAll(\\"\\\\r\\\\n\\", \\"oops\\\\r\\\\n\\"));" - } - ] -}" -`; - -exports[`java_lang_http_response_splitting ok 1`] = `"{}"`; diff --git a/tests/java/lang/http_response_splitting/test.js b/tests/java/lang/http_response_splitting/test.js index 315cd32b9..9b054bb01 100644 --- a/tests/java/lang/http_response_splitting/test.js +++ b/tests/java/lang/http_response_splitting/test.js @@ -1,29 +1,40 @@ -const { createInvoker, createNewInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.java" - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + const results = invoke(testCase) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("main", () => { + const testCase = "main.java" - // new test cases - const invokeV2 = createNewInvoker(ruleId, ruleFile, testBase) - test("http_response_splitting", () => { - const testCase = "main.java" + const results = invoke(testCase) - const results = invokeV2(testCase) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - expect(results.Missing).toEqual([]) - expect(results.Extra).toEqual([]) - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + }) \ No newline at end of file diff --git a/tests/java/lang/http_response_splitting/testdata/bad.java b/tests/java/lang/http_response_splitting/testdata/bad.java index 6d24f218c..965e23046 100644 --- a/tests/java/lang/http_response_splitting/testdata/bad.java +++ b/tests/java/lang/http_response_splitting/testdata/bad.java @@ -1,12 +1,15 @@ public class Main { public static void main(HttpServletRequest request) { var foo = request.getParameter("foo"); +// bearer:expected java_lang_http_response_splitting new Cookie("oops", foo); var bar = request.getParameter("bar"); var c = new Cookie("oops2", "ok"); +// bearer:expected java_lang_http_response_splitting c.setValue(bar); +// bearer:expected java_lang_http_response_splitting new Cookie("oops3", foo.replaceAll("\r\n", "oops\r\n")); } } diff --git a/tests/java/lang/information_leakage/__snapshots__/test.js.snap b/tests/java/lang/information_leakage/__snapshots__/test.js.snap deleted file mode 100644 index 792096c6e..000000000 --- a/tests/java/lang/information_leakage/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_information_leakage leak 1`] = ` -"{ - "warning": [ - { - "cwe_ids": [ - "209" - ], - "id": "java_lang_information_leakage", - "title": "Leakage of sensitive information in exception message", - "description": "## Description\\n\\nPrinting a stack trace to the default output is risky because it may contain sensitive information such as the technical details of your application or environment (which in turn could expose your application to path traversal attacks, for example), or worse, user-specific data.\\n\\n## Remediations\\n\\n❌ Avoid printing the full stack trace\\n\\n✅ Less is more! Only log the minimum required details in error messages\\n\\n## Resources\\n\\n- [Web Application Security Consortium: Information Leakage](http://projects.webappsec.org/w/page/13246936/Information%20Leakage)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_information_leakage", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/leak.java", - "filename": ".", - "source": { - "start": 8, - "end": 8, - "column": { - "start": 7, - "end": 26 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 7, - "end": 26 - }, - "content": "e.printStackTrace()" - }, - "parent_line_number": 8, - "snippet": "e.printStackTrace()", - "fingerprint": "9fff3d7f302686a23685fc6d2a7ac46c_0", - "old_fingerprint": "44b55b6bf1b6b0a9c92735f6f2b4bf25_0", - "code_extract": " e.printStackTrace();" - } - ] -}" -`; - -exports[`java_lang_information_leakage ok 1`] = `"{}"`; diff --git a/tests/java/lang/information_leakage/test.js b/tests/java/lang/information_leakage/test.js index 76e9a29e8..a8717f37d 100644 --- a/tests/java/lang/information_leakage/test.js +++ b/tests/java/lang/information_leakage/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("leak", () => { + const testCase = "leak.java" + + const results = invoke(testCase) - test("leak", () => { - const testCase = "leak.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/information_leakage/testdata/leak.java b/tests/java/lang/information_leakage/testdata/leak.java index a3adf8198..943ad4fa1 100644 --- a/tests/java/lang/information_leakage/testdata/leak.java +++ b/tests/java/lang/information_leakage/testdata/leak.java @@ -5,6 +5,7 @@ public static void main() { } catch (Exception e) { +// bearer:expected java_lang_information_leakage e.printStackTrace(); } } diff --git a/tests/java/lang/insecure_cookie/__snapshots__/test.js.snap b/tests/java/lang/insecure_cookie/__snapshots__/test.js.snap deleted file mode 100644 index 8a28d5a36..000000000 --- a/tests/java/lang/insecure_cookie/__snapshots__/test.js.snap +++ /dev/null @@ -1,80 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_insecure_cookie bad 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "614" - ], - "id": "java_lang_insecure_cookie", - "title": "Missing secure options for cookie detected", - "description": "## Description\\n\\nTo make sure cookies don't open your application up to exploits or unauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n\\n✅ Set \`Secure\` to \`true\` to force cookies to only be sent over HTTPS\\n\\n\`\`\`java\\ncookie.setSecure(true);\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_insecure_cookie", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 8, - "end": 8, - "column": { - "start": 5, - "end": 24 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 5, - "end": 24 - }, - "content": "c1.setSecure(false)" - }, - "parent_line_number": 8, - "snippet": "c1.setSecure(false)", - "fingerprint": "ebb3bb66f61c10a70c9710467ac46faf_0", - "old_fingerprint": "5221acf9beea014b2cdb88e2ee84fbd0_0", - "code_extract": " c1.setSecure(false);" - }, - { - "cwe_ids": [ - "614" - ], - "id": "java_lang_insecure_cookie", - "title": "Missing secure options for cookie detected", - "description": "## Description\\n\\nTo make sure cookies don't open your application up to exploits or unauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n\\n✅ Set \`Secure\` to \`true\` to force cookies to only be sent over HTTPS\\n\\n\`\`\`java\\ncookie.setSecure(true);\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_insecure_cookie", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 5, - "end": 20 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 5, - "end": 20 - }, - "content": "c2.setSecure(f)" - }, - "parent_line_number": 12, - "snippet": "c2.setSecure(f)", - "fingerprint": "ebb3bb66f61c10a70c9710467ac46faf_1", - "old_fingerprint": "5221acf9beea014b2cdb88e2ee84fbd0_1", - "code_extract": " c2.setSecure(f);" - } - ] -}" -`; - -exports[`java_lang_insecure_cookie bad_http_only 1`] = `"{}"`; - -exports[`java_lang_insecure_cookie ok 1`] = `"{}"`; diff --git a/tests/java/lang/insecure_cookie/test.js b/tests/java/lang/insecure_cookie/test.js index 217792e2d..0087c5d56 100644 --- a/tests/java/lang/insecure_cookie/test.js +++ b/tests/java/lang/insecure_cookie/test.js @@ -1,25 +1,40 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.java" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("bad_http_only", () => { - const testCase = "bad_http_only.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("bad_http_only", () => { + const testCase = "bad_http_only.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/insecure_cookie/testdata/bad.java b/tests/java/lang/insecure_cookie/testdata/bad.java index ddded0ba9..3f1b95e0a 100644 --- a/tests/java/lang/insecure_cookie/testdata/bad.java +++ b/tests/java/lang/insecure_cookie/testdata/bad.java @@ -5,10 +5,12 @@ public class Test public void cookie() { Cookie c1 = new Cookie("c1", "foo"); +// bearer:expected java_lang_insecure_cookie c1.setSecure(false); boolean f = false; javax.servlet.http.Cookie c2 = new javax.servlet.http.Cookie("c2", "bar"); +// bearer:expected java_lang_insecure_cookie c2.setSecure(f); } } diff --git a/tests/java/lang/insufficiently_random_values/__snapshots__/test.js.snap b/tests/java/lang/insufficiently_random_values/__snapshots__/test.js.snap deleted file mode 100644 index b580be227..000000000 --- a/tests/java/lang/insufficiently_random_values/__snapshots__/test.js.snap +++ /dev/null @@ -1,214 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_insufficiently_random_values bad 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "330" - ], - "id": "java_lang_insufficiently_random_values", - "title": "Usage of insufficient random value", - "description": "## Description\\n\\nUsing predictable random values makes our application vulnerable to attacks,\\nespecially if these values are used for security purposes.\\n\\n## Remediations\\n\\n✅ Use a stronger library when generating random values\\n\\n\`\`\`java\\nSecureRandom random = new SecureRandom();\\n\`\`\`\\n\\n## Resources\\n- [Java SecureRandom class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/SecureRandom.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_insufficiently_random_values", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 15, - "end": 27 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 15, - "end": 27 - }, - "content": "new Random()" - }, - "parent_line_number": 1, - "snippet": "new Random()", - "fingerprint": "8f51671abbce2a871cc191dc35531c9f_0", - "old_fingerprint": "32a0cd15fe8bb40ad4a1cfb2d4b4da96_0", - "code_extract": "Random rand = new Random();" - }, - { - "cwe_ids": [ - "330" - ], - "id": "java_lang_insufficiently_random_values", - "title": "Usage of insufficient random value", - "description": "## Description\\n\\nUsing predictable random values makes our application vulnerable to attacks,\\nespecially if these values are used for security purposes.\\n\\n## Remediations\\n\\n✅ Use a stronger library when generating random values\\n\\n\`\`\`java\\nSecureRandom random = new SecureRandom();\\n\`\`\`\\n\\n## Resources\\n- [Java SecureRandom class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/SecureRandom.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_insufficiently_random_values", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 53 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 53 - }, - "content": "org.apache.commons.lang.RandomStringUtils.random(10)" - }, - "parent_line_number": 4, - "snippet": "org.apache.commons.lang.RandomStringUtils.random(10)", - "fingerprint": "8f51671abbce2a871cc191dc35531c9f_1", - "old_fingerprint": "32a0cd15fe8bb40ad4a1cfb2d4b4da96_1", - "code_extract": "org.apache.commons.lang.RandomStringUtils.random(10);" - }, - { - "cwe_ids": [ - "330" - ], - "id": "java_lang_insufficiently_random_values", - "title": "Usage of insufficient random value", - "description": "## Description\\n\\nUsing predictable random values makes our application vulnerable to attacks,\\nespecially if these values are used for security purposes.\\n\\n## Remediations\\n\\n✅ Use a stronger library when generating random values\\n\\n\`\`\`java\\nSecureRandom random = new SecureRandom();\\n\`\`\`\\n\\n## Resources\\n- [Java SecureRandom class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/SecureRandom.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_insufficiently_random_values", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 29 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 29 - }, - "content": "RandomStringUtils.random(10)" - }, - "parent_line_number": 5, - "snippet": "RandomStringUtils.random(10)", - "fingerprint": "8f51671abbce2a871cc191dc35531c9f_2", - "old_fingerprint": "32a0cd15fe8bb40ad4a1cfb2d4b4da96_2", - "code_extract": "RandomStringUtils.random(10);" - }, - { - "cwe_ids": [ - "330" - ], - "id": "java_lang_insufficiently_random_values", - "title": "Usage of insufficient random value", - "description": "## Description\\n\\nUsing predictable random values makes our application vulnerable to attacks,\\nespecially if these values are used for security purposes.\\n\\n## Remediations\\n\\n✅ Use a stronger library when generating random values\\n\\n\`\`\`java\\nSecureRandom random = new SecureRandom();\\n\`\`\`\\n\\n## Resources\\n- [Java SecureRandom class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/SecureRandom.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_insufficiently_random_values", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 7, - "end": 7, - "column": { - "start": 1, - "end": 51 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 1, - "end": 51 - }, - "content": "org.apache.commons.lang.math.RandomUtils.nextint()" - }, - "parent_line_number": 7, - "snippet": "org.apache.commons.lang.math.RandomUtils.nextint()", - "fingerprint": "8f51671abbce2a871cc191dc35531c9f_3", - "old_fingerprint": "32a0cd15fe8bb40ad4a1cfb2d4b4da96_3", - "code_extract": "org.apache.commons.lang.math.RandomUtils.nextint();" - }, - { - "cwe_ids": [ - "330" - ], - "id": "java_lang_insufficiently_random_values", - "title": "Usage of insufficient random value", - "description": "## Description\\n\\nUsing predictable random values makes our application vulnerable to attacks,\\nespecially if these values are used for security purposes.\\n\\n## Remediations\\n\\n✅ Use a stronger library when generating random values\\n\\n\`\`\`java\\nSecureRandom random = new SecureRandom();\\n\`\`\`\\n\\n## Resources\\n- [Java SecureRandom class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/SecureRandom.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_insufficiently_random_values", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 8, - "end": 8, - "column": { - "start": 1, - "end": 22 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 1, - "end": 22 - }, - "content": "RandomUtils.nextint()" - }, - "parent_line_number": 8, - "snippet": "RandomUtils.nextint()", - "fingerprint": "8f51671abbce2a871cc191dc35531c9f_4", - "old_fingerprint": "32a0cd15fe8bb40ad4a1cfb2d4b4da96_4", - "code_extract": "RandomUtils.nextint();" - }, - { - "cwe_ids": [ - "330" - ], - "id": "java_lang_insufficiently_random_values", - "title": "Usage of insufficient random value", - "description": "## Description\\n\\nUsing predictable random values makes our application vulnerable to attacks,\\nespecially if these values are used for security purposes.\\n\\n## Remediations\\n\\n✅ Use a stronger library when generating random values\\n\\n\`\`\`java\\nSecureRandom random = new SecureRandom();\\n\`\`\`\\n\\n## Resources\\n- [Java SecureRandom class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/SecureRandom.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_insufficiently_random_values", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 12, - "end": 35 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 12, - "end": 35 - }, - "content": "java.lang.Math.random()" - }, - "parent_line_number": 10, - "snippet": "java.lang.Math.random()", - "fingerprint": "8f51671abbce2a871cc191dc35531c9f_5", - "old_fingerprint": "32a0cd15fe8bb40ad4a1cfb2d4b4da96_5", - "code_extract": "double v = java.lang.Math.random();" - } - ] -}" -`; - -exports[`java_lang_insufficiently_random_values ok_secure_random 1`] = `"{}"`; diff --git a/tests/java/lang/insufficiently_random_values/test.js b/tests/java/lang/insufficiently_random_values/test.js index cd112229b..9f6089046 100644 --- a/tests/java/lang/insufficiently_random_values/test.js +++ b/tests/java/lang/insufficiently_random_values/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.java" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_secure_random", () => { - const testCase = "ok_secure_random.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_secure_random", () => { + const testCase = "ok_secure_random.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/insufficiently_random_values/testdata/bad.java b/tests/java/lang/insufficiently_random_values/testdata/bad.java index 71fad3712..9eb9e71a6 100644 --- a/tests/java/lang/insufficiently_random_values/testdata/bad.java +++ b/tests/java/lang/insufficiently_random_values/testdata/bad.java @@ -1,10 +1,16 @@ +// bearer:expected java_lang_insufficiently_random_values Random rand = new Random(); rand.next(); +// bearer:expected java_lang_insufficiently_random_values org.apache.commons.lang.RandomStringUtils.random(10); +// bearer:expected java_lang_insufficiently_random_values RandomStringUtils.random(10); +// bearer:expected java_lang_insufficiently_random_values org.apache.commons.lang.math.RandomUtils.nextint(); +// bearer:expected java_lang_insufficiently_random_values RandomUtils.nextint(); +// bearer:expected java_lang_insufficiently_random_values double v = java.lang.Math.random(); diff --git a/tests/java/lang/ldap_injection/__snapshots__/test.js.snap b/tests/java/lang/ldap_injection/__snapshots__/test.js.snap deleted file mode 100644 index ad2ffe896..000000000 --- a/tests/java/lang/ldap_injection/__snapshots__/test.js.snap +++ /dev/null @@ -1,42 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_ldap_injection ldap_injection 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "90" - ], - "id": "java_lang_ldap_injection", - "title": "Unsanitized user input in LDAP request", - "description": "## Description\\n Unsatized input going into LDAP query detected. This could lead to LDAP injection, which could result in attackers modifying objects in the LDAP tree structure. Ensure data passed to an LDAP query is not controllable or properly sanitize the data.\\n\\n## Remediations\\n\\n✅ Sanitize LDAP query data\\n\\n\`\`\`java\\n public class Cls extends HttpServlet\\n {\\n\\n public void handleRequest(HttpServletRequest request, HttpServletResponse response)\\n {\\n String userID = request.getParameter(\\"userID\\");\\n String sanitizedUserID = sanitize(userID);\\n\\n String filter = \\"(&(objectclass=person))(|(uid=\\" + sanitizedUserID + \\")(street={0}))\\";\\n String base = \\"ou=users,ou=system\\";\\n Object[] filters = new Object[] {\\"First avenue\\"};\\n javax.naming.directory.SearchControls sc = new javax.naming.directory.SearchControls();\\n\\n dirContext.search(base, filter, filters, sc);\\n }\\n }\\n\`\`\`\\n\\n## References\\n- [LDAP Injection](https://owasp.org/www-community/attacks/LDAP_Injection)\\n- [LDAP Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_ldap_injection", - "line_number": 17, - "full_filename": "/tmp/bearer-scan/ldap_injection.java", - "filename": ".", - "source": { - "start": 17, - "end": 17, - "column": { - "start": 9, - "end": 53 - } - }, - "sink": { - "start": 17, - "end": 17, - "column": { - "start": 9, - "end": 53 - }, - "content": "dirContext.search(base, filter, filters, sc)" - }, - "parent_line_number": 17, - "snippet": "dirContext.search(base, filter, filters, sc)", - "fingerprint": "0bad406b42c52ab03e6e7a64c501440d_0", - "old_fingerprint": "091cee7b38ff59746e5d6fb2bdb8328a_0", - "code_extract": " dirContext.search(base, filter, filters, sc);" - } - ] -}" -`; diff --git a/tests/java/lang/ldap_injection/test.js b/tests/java/lang/ldap_injection/test.js index 912e22da7..6685f3154 100644 --- a/tests/java/lang/ldap_injection/test.js +++ b/tests/java/lang/ldap_injection/test.js @@ -1,13 +1,20 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("ldap_injection", () => { + const testCase = "ldap_injection.java" + + const results = invoke(testCase) - test("ldap_injection", () => { - const testCase = "ldap_injection.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/ldap_injection/testdata/ldap_injection.java b/tests/java/lang/ldap_injection/testdata/ldap_injection.java index e3a043aae..242e9716e 100644 --- a/tests/java/lang/ldap_injection/testdata/ldap_injection.java +++ b/tests/java/lang/ldap_injection/testdata/ldap_injection.java @@ -14,6 +14,7 @@ public void handleRequest(HttpServletRequest request, HttpServletResponse respon DirContext dirContext = new InitialDirContext(env); +// bearer:expected java_lang_ldap_injection dirContext.search(base, filter, filters, sc); } } \ No newline at end of file diff --git a/tests/java/lang/log_injection/__snapshots__/test.js.snap b/tests/java/lang/log_injection/__snapshots__/test.js.snap deleted file mode 100644 index 26a5ed436..000000000 --- a/tests/java/lang/log_injection/__snapshots__/test.js.snap +++ /dev/null @@ -1,110 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_log_injection log_injection 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "117" - ], - "id": "java_lang_log_injection", - "title": "Unsanitized user input in logger message", - "description": "## Description\\nWriting invalidated user input to log files can allow an attacker to forge log entries or inject malicious content into the logs. This rule looks for instances of user input sent to loggers.\\n## Remediations\\n❌ Avoid using unsanitized user input in logger messages:\\n\`\`\`java\\n String username = request.getParameter(\\"username\\");\\n log.warn(\\"Username is\\" + username);\\n\`\`\`\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\`\`\`java\\n String username = sanitized(request.getParameter(\\"username\\"));\\n log.warn(\\"Username is\\" + username);\\n\`\`\`\\n## Resources\\n- [OWASP Log Injection] (https://owasp.org/www-community/attacks/Log_Injection)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_logger", - "line_number": 17, - "full_filename": "/tmp/bearer-scan/log_injection.java", - "filename": ".", - "source": { - "start": 17, - "end": 17, - "column": { - "start": 13, - "end": 71 - } - }, - "sink": { - "start": 17, - "end": 17, - "column": { - "start": 13, - "end": 71 - }, - "content": "log.info(\\"Username is\\" + request.getParameter(\\"username\\"))" - }, - "parent_line_number": 17, - "snippet": "log.info(\\"Username is\\" + request.getParameter(\\"username\\"))", - "fingerprint": "729129102c16042b19d35640a9d9b661_0", - "old_fingerprint": "a45c0a68b3af767b3565879508913c0d_0", - "code_extract": " log.info(\\"Username is\\" + request.getParameter(\\"username\\"));" - }, - { - "cwe_ids": [ - "117" - ], - "id": "java_lang_log_injection", - "title": "Unsanitized user input in logger message", - "description": "## Description\\nWriting invalidated user input to log files can allow an attacker to forge log entries or inject malicious content into the logs. This rule looks for instances of user input sent to loggers.\\n## Remediations\\n❌ Avoid using unsanitized user input in logger messages:\\n\`\`\`java\\n String username = request.getParameter(\\"username\\");\\n log.warn(\\"Username is\\" + username);\\n\`\`\`\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\`\`\`java\\n String username = sanitized(request.getParameter(\\"username\\"));\\n log.warn(\\"Username is\\" + username);\\n\`\`\`\\n## Resources\\n- [OWASP Log Injection] (https://owasp.org/www-community/attacks/Log_Injection)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_logger", - "line_number": 18, - "full_filename": "/tmp/bearer-scan/log_injection.java", - "filename": ".", - "source": { - "start": 18, - "end": 18, - "column": { - "start": 13, - "end": 47 - } - }, - "sink": { - "start": 18, - "end": 18, - "column": { - "start": 13, - "end": 47 - }, - "content": "log.warn(\\"Username is\\" + username)" - }, - "parent_line_number": 18, - "snippet": "log.warn(\\"Username is\\" + username)", - "fingerprint": "729129102c16042b19d35640a9d9b661_1", - "old_fingerprint": "a45c0a68b3af767b3565879508913c0d_1", - "code_extract": " log.warn(\\"Username is\\" + username);" - }, - { - "cwe_ids": [ - "117" - ], - "id": "java_lang_log_injection", - "title": "Unsanitized user input in logger message", - "description": "## Description\\nWriting invalidated user input to log files can allow an attacker to forge log entries or inject malicious content into the logs. This rule looks for instances of user input sent to loggers.\\n## Remediations\\n❌ Avoid using unsanitized user input in logger messages:\\n\`\`\`java\\n String username = request.getParameter(\\"username\\");\\n log.warn(\\"Username is\\" + username);\\n\`\`\`\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\`\`\`java\\n String username = sanitized(request.getParameter(\\"username\\"));\\n log.warn(\\"Username is\\" + username);\\n\`\`\`\\n## Resources\\n- [OWASP Log Injection] (https://owasp.org/www-community/attacks/Log_Injection)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_logger", - "line_number": 19, - "full_filename": "/tmp/bearer-scan/log_injection.java", - "filename": ".", - "source": { - "start": 19, - "end": 19, - "column": { - "start": 13, - "end": 32 - } - }, - "sink": { - "start": 19, - "end": 19, - "column": { - "start": 13, - "end": 32 - }, - "content": "log.error(username)" - }, - "parent_line_number": 19, - "snippet": "log.error(username)", - "fingerprint": "729129102c16042b19d35640a9d9b661_2", - "old_fingerprint": "a45c0a68b3af767b3565879508913c0d_2", - "code_extract": " log.error(username);" - } - ] -}" -`; diff --git a/tests/java/lang/log_injection/test.js b/tests/java/lang/log_injection/test.js index ec3a52104..39a8be318 100644 --- a/tests/java/lang/log_injection/test.js +++ b/tests/java/lang/log_injection/test.js @@ -1,24 +1,30 @@ -const { createInvoker, createNewInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) - test("log_injection", () => { - const testCase = "log_injection.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + + test("log_injection", () => { + const testCase = "log_injection.java" - // new style tests - const invokeV2 = createNewInvoker(ruleId, ruleFile, testBase) + const results = invoke(testCase) - test("log_injection_v2", () => { - const testCase = "main.java" + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - const results = invokeV2(testCase) + test("main", () => { + const testCase = "main.java" - expect(results.Missing).toEqual([]) - expect(results.Extra).toEqual([]) - }) + const results = invoke(testCase) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + }) \ No newline at end of file diff --git a/tests/java/lang/log_injection/testdata/log_injection.java b/tests/java/lang/log_injection/testdata/log_injection.java index 0a6dd55a5..9b7196fd1 100644 --- a/tests/java/lang/log_injection/testdata/log_injection.java +++ b/tests/java/lang/log_injection/testdata/log_injection.java @@ -14,8 +14,11 @@ public void logInjection(HttpServletRequest request, HttpServletResponse respons { log = Logger.getLogger(Log.class); String username = request.getParameter("username"); +// bearer:expected java_lang_log_injection log.info("Username is" + request.getParameter("username")); +// bearer:expected java_lang_log_injection log.warn("Username is" + username); +// bearer:expected java_lang_log_injection log.error(username); log.error("This is not finding"); diff --git a/tests/java/lang/logger/__snapshots__/test.js.snap b/tests/java/lang/logger/__snapshots__/test.js.snap deleted file mode 100644 index c28099214..000000000 --- a/tests/java/lang/logger/__snapshots__/test.js.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_logger simple 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "532" - ], - "id": "java_lang_logger", - "title": "Leakage of sensitive information in logger message", - "description": "## Description\\n\\nLeaking sensitive data to loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to loggers.\\n\\n## Remediations\\n\\n❌ Avoid using sensitive data in logger messages:\\n\\n\`\`\`java\\nlogger.info(user.email)\\n\`\`\`\\n\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`java\\nlogger.info(user.uuid)\\n\`\`\`\\n\\n✅ Ideally, do not log dynamic variables or attributes as this could lead to unintentional information leakage down the line\\n\\n\`\`\`java\\nlogger.info(\\"user signed in\\")\\n\`\`\`\\n## Resources\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_logger", - "line_number": 16, - "full_filename": "/tmp/bearer-scan/simple.java", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 16, - "end": 16, - "column": { - "start": 26, - "end": 35 - } - }, - "sink": { - "start": 16, - "end": 16, - "column": { - "start": 13, - "end": 36 - }, - "content": "logger.error(user.name)" - }, - "parent_line_number": 16, - "snippet": "logger.error(user.name)", - "fingerprint": "14b8421b91dfd6860ab797a528643c7f_0", - "old_fingerprint": "52b4f9ef975cdb0ca989d6f9b7b721db_0", - "code_extract": " logger.error(user.name);" - } - ] -}" -`; diff --git a/tests/java/lang/logger/test.js b/tests/java/lang/logger/test.js index d619430ed..452b02019 100644 --- a/tests/java/lang/logger/test.js +++ b/tests/java/lang/logger/test.js @@ -1,13 +1,20 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("simple", () => { + const testCase = "simple.java" + + const results = invoke(testCase) - test("simple", () => { - const testCase = "simple.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/logger/testdata/simple.java b/tests/java/lang/logger/testdata/simple.java index 835be3940..5d5f2693b 100644 --- a/tests/java/lang/logger/testdata/simple.java +++ b/tests/java/lang/logger/testdata/simple.java @@ -13,6 +13,7 @@ public class Cls extends HttpServlet public void handleRequest(HttpServletRequest request, HttpServletResponse response) { User user; +// bearer:expected java_lang_logger logger.error(user.name); logger.error(user.name ? "ok": "ok"); } diff --git a/tests/java/lang/missing_database_authentication/__snapshots__/test.js.snap b/tests/java/lang/missing_database_authentication/__snapshots__/test.js.snap deleted file mode 100644 index 1bf91fe54..000000000 --- a/tests/java/lang/missing_database_authentication/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_missing_database_authentication bad 1`] = ` -"{ - "warning": [ - { - "cwe_ids": [ - "306" - ], - "id": "java_lang_missing_database_authentication", - "title": "Missing authentication for database", - "description": "## Description\\n\\nA database server with inadequate authentication is extremely vulnerable to security attacks.\\nEnsure that your database server has the recommended authentication configuration (password, username), and consider using a key management system for any passwords.\\n\\n## Resources\\n\\n- [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_missing_database_authentication", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 8, - "end": 8, - "column": { - "start": 23, - "end": 67 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 23, - "end": 67 - }, - "content": "DriverManager.getConnection(url, \\"root\\", \\"\\")" - }, - "parent_line_number": 8, - "snippet": "DriverManager.getConnection(url, \\"root\\", \\"\\")", - "fingerprint": "c604e41b22b8045034a2fdf34214a28c_0", - "old_fingerprint": "561bd711639a61295d21d7d593d46497_0", - "code_extract": " Connection conn = DriverManager.getConnection(url, \\"root\\", \\"\\");" - } - ] -}" -`; - -exports[`java_lang_missing_database_authentication ok 1`] = `"{}"`; diff --git a/tests/java/lang/missing_database_authentication/test.js b/tests/java/lang/missing_database_authentication/test.js index 3c77c7b9d..e79f6c542 100644 --- a/tests/java/lang/missing_database_authentication/test.js +++ b/tests/java/lang/missing_database_authentication/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.java" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/missing_database_authentication/testdata/bad.java b/tests/java/lang/missing_database_authentication/testdata/bad.java index c296db0a9..95e9d68fb 100644 --- a/tests/java/lang/missing_database_authentication/testdata/bad.java +++ b/tests/java/lang/missing_database_authentication/testdata/bad.java @@ -5,6 +5,7 @@ public class Foo { public static void main() { String url = "jdbc:mysql://localhost:3306/foo"; +// bearer:expected java_lang_missing_database_authentication Connection conn = DriverManager.getConnection(url, "root", ""); } } \ No newline at end of file diff --git a/tests/java/lang/missing_integrity_check/__snapshots__/test.js.snap b/tests/java/lang/missing_integrity_check/__snapshots__/test.js.snap deleted file mode 100644 index fb73bfcd9..000000000 --- a/tests/java/lang/missing_integrity_check/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_missing_integrity_check missing_integrity_check 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "353" - ], - "id": "java_lang_missing_integrity_check", - "title": "Missing support for integrity check", - "description": "## Description\\n\\nIf a protocol does not include integrity checks (\\"checksums\\"), we cannot determine whether or not an attacker has interfered or manipulated the transmitted data (man-in-the-middle attack).\\n\\n## Remediations\\n\\n✅ Use encryption schemes that provide integrity\\n\\n\`\`\`java\\n Cipher c = Cipher.getInstance(\\"AES/GCM/PKCS5Padding\\");\\n\`\`\`\\n\\n## Resources\\n- [Java Cipher class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/javax/crypto/Cipher.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_missing_integrity_check", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/missing_integrity_check.java", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 14, - "end": 56 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 14, - "end": 56 - }, - "content": "Cipher.getInstance(\\"DES/CBC/PKCS5Padding\\")" - }, - "parent_line_number": 3, - "snippet": "Cipher.getInstance(\\"DES/CBC/PKCS5Padding\\")", - "fingerprint": "087c203d46f2b806e4210f7c517bfe40_0", - "old_fingerprint": "f0d248a05ed8bbe1ec9fd08c8eb36eb6_0", - "code_extract": " Cipher c = Cipher.getInstance(\\"DES/CBC/PKCS5Padding\\");" - } - ] -}" -`; - -exports[`java_lang_missing_integrity_check ok 1`] = `"{}"`; diff --git a/tests/java/lang/missing_integrity_check/test.js b/tests/java/lang/missing_integrity_check/test.js index 2ba5646f3..32ea4f5f5 100644 --- a/tests/java/lang/missing_integrity_check/test.js +++ b/tests/java/lang/missing_integrity_check/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("missing_integrity_check", () => { + const testCase = "missing_integrity_check.java" + + const results = invoke(testCase) - test("missing_integrity_check", () => { - const testCase = "missing_integrity_check.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/missing_integrity_check/testdata/missing_integrity_check.java b/tests/java/lang/missing_integrity_check/testdata/missing_integrity_check.java index 55cf16455..b8593cc75 100644 --- a/tests/java/lang/missing_integrity_check/testdata/missing_integrity_check.java +++ b/tests/java/lang/missing_integrity_check/testdata/missing_integrity_check.java @@ -1,5 +1,6 @@ public byte[] encryptMe(String text) throws GeneralSecurityException { +// bearer:expected java_lang_missing_integrity_check Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding"); c.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate()); diff --git a/tests/java/lang/os_command_injection/__snapshots__/test.js.snap b/tests/java/lang/os_command_injection/__snapshots__/test.js.snap deleted file mode 100644 index 509544ece..000000000 --- a/tests/java/lang/os_command_injection/__snapshots__/test.js.snap +++ /dev/null @@ -1,146 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_os_command_injection bad 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "78" - ], - "id": "java_lang_os_command_injection", - "title": "Unsanitized user input in OS command", - "description": "## Description\\n\\nUsing external or user-defined input directly in an OS command can allow attackers to perform dangerous commands on the operating system.\\n\\n## Remediations\\n\\n❌ Avoid using OS commands, with or without dynamic input, wherever possible. For example, look for an equivalent library or function to use instead.\\n\\n✅ For dynamic input, rely on hardcoded values wherever possible\\n\\n\`\`\`java\\n String filePattern = \\"*.json\\";\\n if request.getParameter(\\"format\\") == \\"xml\\" {\\n filePattern = \\"*.xml\\"\\n }\\n\\n Process process = Runtime.getRuntime().exec(\\"ls /myDir/\\" + extension);\\n\`\`\`\\n\\n## Resources\\n- [OWASP command injection explained](https://owasp.org/www-community/attacks/Command_Injection)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_os_command_injection", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 9, - "end": 37 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 9, - "end": 37 - }, - "content": "r.exec(\\"sh -c echo \\" + name)" - }, - "parent_line_number": 10, - "snippet": "r.exec(\\"sh -c echo \\" + name)", - "fingerprint": "5665fcfd14328e5c667ee31b32dffafd_0", - "old_fingerprint": "a0ce9f3043b13a6baf7c16fd7608b765_0", - "code_extract": " r.exec(\\"sh -c echo \\" + name);" - }, - { - "cwe_ids": [ - "78" - ], - "id": "java_lang_os_command_injection", - "title": "Unsanitized user input in OS command", - "description": "## Description\\n\\nUsing external or user-defined input directly in an OS command can allow attackers to perform dangerous commands on the operating system.\\n\\n## Remediations\\n\\n❌ Avoid using OS commands, with or without dynamic input, wherever possible. For example, look for an equivalent library or function to use instead.\\n\\n✅ For dynamic input, rely on hardcoded values wherever possible\\n\\n\`\`\`java\\n String filePattern = \\"*.json\\";\\n if request.getParameter(\\"format\\") == \\"xml\\" {\\n filePattern = \\"*.xml\\"\\n }\\n\\n Process process = Runtime.getRuntime().exec(\\"ls /myDir/\\" + extension);\\n\`\`\`\\n\\n## Resources\\n- [OWASP command injection explained](https://owasp.org/www-community/attacks/Command_Injection)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_os_command_injection", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 9, - "end": 56 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 9, - "end": 56 - }, - "content": "Runtime.getRuntime().exec(\\"sh -c echo \\" + name)" - }, - "parent_line_number": 12, - "snippet": "Runtime.getRuntime().exec(\\"sh -c echo \\" + name)", - "fingerprint": "5665fcfd14328e5c667ee31b32dffafd_1", - "old_fingerprint": "a0ce9f3043b13a6baf7c16fd7608b765_1", - "code_extract": " Runtime.getRuntime().exec(\\"sh -c echo \\" + name);" - }, - { - "cwe_ids": [ - "78" - ], - "id": "java_lang_os_command_injection", - "title": "Unsanitized user input in OS command", - "description": "## Description\\n\\nUsing external or user-defined input directly in an OS command can allow attackers to perform dangerous commands on the operating system.\\n\\n## Remediations\\n\\n❌ Avoid using OS commands, with or without dynamic input, wherever possible. For example, look for an equivalent library or function to use instead.\\n\\n✅ For dynamic input, rely on hardcoded values wherever possible\\n\\n\`\`\`java\\n String filePattern = \\"*.json\\";\\n if request.getParameter(\\"format\\") == \\"xml\\" {\\n filePattern = \\"*.xml\\"\\n }\\n\\n Process process = Runtime.getRuntime().exec(\\"ls /myDir/\\" + extension);\\n\`\`\`\\n\\n## Resources\\n- [OWASP command injection explained](https://owasp.org/www-community/attacks/Command_Injection)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_os_command_injection", - "line_number": 18, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 18, - "end": 18, - "column": { - "start": 29, - "end": 69 - } - }, - "sink": { - "start": 18, - "end": 18, - "column": { - "start": 29, - "end": 69 - }, - "content": "new ProcessBuilder(\\"sh -c echo \\" + name)" - }, - "parent_line_number": 18, - "snippet": "new ProcessBuilder(\\"sh -c echo \\" + name)", - "fingerprint": "5665fcfd14328e5c667ee31b32dffafd_2", - "old_fingerprint": "a0ce9f3043b13a6baf7c16fd7608b765_2", - "code_extract": " ProcessBuilder pb = new ProcessBuilder(\\"sh -c echo \\" + name);" - }, - { - "cwe_ids": [ - "78" - ], - "id": "java_lang_os_command_injection", - "title": "Unsanitized user input in OS command", - "description": "## Description\\n\\nUsing external or user-defined input directly in an OS command can allow attackers to perform dangerous commands on the operating system.\\n\\n## Remediations\\n\\n❌ Avoid using OS commands, with or without dynamic input, wherever possible. For example, look for an equivalent library or function to use instead.\\n\\n✅ For dynamic input, rely on hardcoded values wherever possible\\n\\n\`\`\`java\\n String filePattern = \\"*.json\\";\\n if request.getParameter(\\"format\\") == \\"xml\\" {\\n filePattern = \\"*.xml\\"\\n }\\n\\n Process process = Runtime.getRuntime().exec(\\"ls /myDir/\\" + extension);\\n\`\`\`\\n\\n## Resources\\n- [OWASP command injection explained](https://owasp.org/www-community/attacks/Command_Injection)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_os_command_injection", - "line_number": 21, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 21, - "end": 21, - "column": { - "start": 9, - "end": 41 - } - }, - "sink": { - "start": 21, - "end": 21, - "column": { - "start": 9, - "end": 41 - }, - "content": "pb.command(\\"sh -c echo \\" + name)" - }, - "parent_line_number": 21, - "snippet": "pb.command(\\"sh -c echo \\" + name)", - "fingerprint": "5665fcfd14328e5c667ee31b32dffafd_3", - "old_fingerprint": "a0ce9f3043b13a6baf7c16fd7608b765_3", - "code_extract": " pb.command(\\"sh -c echo \\" + name);" - } - ] -}" -`; - -exports[`java_lang_os_command_injection ok 1`] = `"{}"`; diff --git a/tests/java/lang/os_command_injection/test.js b/tests/java/lang/os_command_injection/test.js index 3c77c7b9d..e79f6c542 100644 --- a/tests/java/lang/os_command_injection/test.js +++ b/tests/java/lang/os_command_injection/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.java" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/os_command_injection/testdata/bad.java b/tests/java/lang/os_command_injection/testdata/bad.java index 6d44095c9..f2d50cc7e 100644 --- a/tests/java/lang/os_command_injection/testdata/bad.java +++ b/tests/java/lang/os_command_injection/testdata/bad.java @@ -7,17 +7,21 @@ public void badExec(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); Runtime r = Runtime.getRuntime(); +// bearer:expected java_lang_os_command_injection r.exec("sh -c echo " + name); +// bearer:expected java_lang_os_command_injection Runtime.getRuntime().exec("sh -c echo " + name); } public void badProcess(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); +// bearer:expected java_lang_os_command_injection ProcessBuilder pb = new ProcessBuilder("sh -c echo " + name); Process p = pb.start(); +// bearer:expected java_lang_os_command_injection pb.command("sh -c echo " + name); } } diff --git a/tests/java/lang/padding_oracle_encryption_vulnerability/__snapshots__/test.js.snap b/tests/java/lang/padding_oracle_encryption_vulnerability/__snapshots__/test.js.snap deleted file mode 100644 index 2f3c38f5d..000000000 --- a/tests/java/lang/padding_oracle_encryption_vulnerability/__snapshots__/test.js.snap +++ /dev/null @@ -1,46 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_padding_oracle_encryption_vulnerability block_cipher 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "327" - ], - "id": "java_lang_padding_oracle_encryption_vulnerability", - "title": "Usage of CBC (Cipher Block Chaining) mode with padding", - "description": "## Description\\n\\nUsing a block cipher algorithm mode, such as CBC, together with a padding scheme is vulnerable to Padding Oracle attacks.\\n\\n## Remediations\\n\\n❌ Do not use CBC (Cipher Block Chaining) mode with padding\\n\\n\`\`\`java\\n Cipher c = Cipher.getInstance(\\"AES/CBC/PKCS5Padding\\");\\n\`\`\`\\n\\n✅ Prefer GCM (Galois/Counter Mode) instead\\n\\n\`\`\`java\\n Cipher c = Cipher.getInstance(\\"AES/GCM/PKCS5Padding\\");\\n\`\`\`\\n\\n## Resources\\n- [Java Cipher class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/javax/crypto/Cipher.html)\\n- [Java Security Standard Algorithm Names](https://docs.oracle.com/en/java/javase/20/docs/specs/security/standard-names.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_padding_oracle_encryption_vulnerability", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/block_cipher.java", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 14, - "end": 69 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 14, - "end": 69 - }, - "content": "javax.crypto.Cipher.getInstance(\\"AES/CBC/PKCS5Padding\\")" - }, - "parent_line_number": 3, - "snippet": "javax.crypto.Cipher.getInstance(\\"AES/CBC/PKCS5Padding\\")", - "fingerprint": "368142b7ce98efcf47351ef4a2c2dab7_0", - "old_fingerprint": "36eda5f78aacf8e2f35ba2ebaa30fb01_0", - "code_extract": " Cipher c = javax.crypto.Cipher.getInstance(\\"AES/CBC/PKCS5Padding\\");" - } - ] -}" -`; - -exports[`java_lang_padding_oracle_encryption_vulnerability ok_gcm 1`] = `"{}"`; - -exports[`java_lang_padding_oracle_encryption_vulnerability ok_not_a_block_cipher 1`] = `"{}"`; diff --git a/tests/java/lang/padding_oracle_encryption_vulnerability/test.js b/tests/java/lang/padding_oracle_encryption_vulnerability/test.js index 13e214309..b6cd58ff1 100644 --- a/tests/java/lang/padding_oracle_encryption_vulnerability/test.js +++ b/tests/java/lang/padding_oracle_encryption_vulnerability/test.js @@ -1,25 +1,40 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("block_cipher", () => { + const testCase = "block_cipher.java" + + const results = invoke(testCase) - test("block_cipher", () => { - const testCase = "block_cipher.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_gcm", () => { - const testCase = "ok_gcm.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_gcm", () => { + const testCase = "ok_gcm.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_not_a_block_cipher", () => { - const testCase = "ok_not_a_block_cipher.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_not_a_block_cipher", () => { + const testCase = "ok_not_a_block_cipher.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/padding_oracle_encryption_vulnerability/testdata/block_cipher.java b/tests/java/lang/padding_oracle_encryption_vulnerability/testdata/block_cipher.java index 71c9d4518..cb1cd0d13 100644 --- a/tests/java/lang/padding_oracle_encryption_vulnerability/testdata/block_cipher.java +++ b/tests/java/lang/padding_oracle_encryption_vulnerability/testdata/block_cipher.java @@ -1,5 +1,6 @@ public byte[] signToken(byte[] payload) throws GeneralSecurityException { +// bearer:expected java_lang_padding_oracle_encryption_vulnerability Cipher c = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding"); c.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate()); diff --git a/tests/java/lang/rsa_no_padding/__snapshots__/test.js.snap b/tests/java/lang/rsa_no_padding/__snapshots__/test.js.snap deleted file mode 100644 index bb72d6be6..000000000 --- a/tests/java/lang/rsa_no_padding/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_rsa_no_padding bad_no_padding 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "780" - ], - "id": "java_lang_rsa_no_padding", - "title": "Missing Optimal Asymmetric Encryption Padding (OAEP)", - "description": "## Description\\n\\nThe RSA encryption algorithm is weak when used without Optimal Asymmetric Encryption Padding (OAEP).\\n\\n## Remediations\\n\\n✅ Always use OAEP when using RSA encryption\\n\\n\`\`\`java\\n Cipher cipher = Cipher.getInstance(\\"RSA/ECB/OAEPWithMD5AndMGF1Padding\\")\\n\`\`\`\\n\\n## Resources\\n- [Java MessageDigest class](https://docs.oracle.com/javase/8/docs/api/java/security/MessageDigest.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_rsa_no_padding", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/bad_no_padding.java", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 19, - "end": 72 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 19, - "end": 72 - }, - "content": "javax.crypto.Cipher.getInstance(\\"RSA/NONE/NoPadding\\")" - }, - "parent_line_number": 2, - "snippet": "javax.crypto.Cipher.getInstance(\\"RSA/NONE/NoPadding\\")", - "fingerprint": "9d916a5ca165038ee842b245601b5cf9_0", - "old_fingerprint": "cfcb8fa77628246fb16b15485d82172b_0", - "code_extract": " Cipher cipher = javax.crypto.Cipher.getInstance(\\"RSA/NONE/NoPadding\\");" - } - ] -}" -`; - -exports[`java_lang_rsa_no_padding ok 1`] = `"{}"`; diff --git a/tests/java/lang/rsa_no_padding/test.js b/tests/java/lang/rsa_no_padding/test.js index d21cf3a18..cafd84f9f 100644 --- a/tests/java/lang/rsa_no_padding/test.js +++ b/tests/java/lang/rsa_no_padding/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad_no_padding", () => { + const testCase = "bad_no_padding.java" + + const results = invoke(testCase) - test("bad_no_padding", () => { - const testCase = "bad_no_padding.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/rsa_no_padding/testdata/bad_no_padding.java b/tests/java/lang/rsa_no_padding/testdata/bad_no_padding.java index 71f2fac10..3663997a6 100644 --- a/tests/java/lang/rsa_no_padding/testdata/bad_no_padding.java +++ b/tests/java/lang/rsa_no_padding/testdata/bad_no_padding.java @@ -1,4 +1,5 @@ public Cipher getRSACipher() { +// bearer:expected java_lang_rsa_no_padding Cipher cipher = javax.crypto.Cipher.getInstance("RSA/NONE/NoPadding"); // Some exception handling ... diff --git a/tests/java/lang/sqli/__snapshots__/test.js.snap b/tests/java/lang/sqli/__snapshots__/test.js.snap deleted file mode 100644 index 5dd81c2e2..000000000 --- a/tests/java/lang/sqli/__snapshots__/test.js.snap +++ /dev/null @@ -1,214 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_sqli bad 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "89" - ], - "id": "java_lang_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n Statement stmt = conn.createStatement();\\n ResultSet rs = stmt.executeQuery(\\"select name from users where id='\\"+ uri.getQueryParameter(\\"user_id\\") \\"'\\")) {\\n\`\`\`\\n\\n✅ Instead of using dynamically crafted strings for your SQL queries, use prepared statements instead\\n\\n\`\`\`java\\nmyStmt = myCon.prepareStatement(\\"select * from students where age > ? and name = ?\\");\\nmyStmt.setInt(1, uri.getQueryParameter(\\"age\\"));\\nmyStmt.setString(2, uri.getQueryParameter(\\"name\\"));\\n\`\`\`\\n\\n## Resources\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_sqli", - "line_number": 19, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 19, - "end": 19, - "column": { - "start": 25, - "end": 52 - } - }, - "sink": { - "start": 19, - "end": 19, - "column": { - "start": 25, - "end": 52 - }, - "content": "stmt.executeQuery(sqlQuery)" - }, - "parent_line_number": 19, - "snippet": "stmt.executeQuery(sqlQuery)", - "fingerprint": "79d5d495c5c408c582b32582f1ae9171_0", - "old_fingerprint": "db6f664c606e5cc7e0b287583ab73e93_0", - "code_extract": " ResultSet rs = stmt.executeQuery(sqlQuery);) {" - }, - { - "cwe_ids": [ - "89" - ], - "id": "java_lang_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n Statement stmt = conn.createStatement();\\n ResultSet rs = stmt.executeQuery(\\"select name from users where id='\\"+ uri.getQueryParameter(\\"user_id\\") \\"'\\")) {\\n\`\`\`\\n\\n✅ Instead of using dynamically crafted strings for your SQL queries, use prepared statements instead\\n\\n\`\`\`java\\nmyStmt = myCon.prepareStatement(\\"select * from students where age > ? and name = ?\\");\\nmyStmt.setInt(1, uri.getQueryParameter(\\"age\\"));\\nmyStmt.setString(2, uri.getQueryParameter(\\"name\\"));\\n\`\`\`\\n\\n## Resources\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_sqli", - "line_number": 26, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 26, - "end": 26, - "column": { - "start": 10, - "end": 45 - } - }, - "sink": { - "start": 26, - "end": 26, - "column": { - "start": 10, - "end": 45 - }, - "content": "conn.prepareStatement(sqlQuery, 42)" - }, - "parent_line_number": 26, - "snippet": "conn.prepareStatement(sqlQuery, 42)", - "fingerprint": "79d5d495c5c408c582b32582f1ae9171_1", - "old_fingerprint": "db6f664c606e5cc7e0b287583ab73e93_1", - "code_extract": " conn.prepareStatement(sqlQuery, 42);" - }, - { - "cwe_ids": [ - "89" - ], - "id": "java_lang_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n Statement stmt = conn.createStatement();\\n ResultSet rs = stmt.executeQuery(\\"select name from users where id='\\"+ uri.getQueryParameter(\\"user_id\\") \\"'\\")) {\\n\`\`\`\\n\\n✅ Instead of using dynamically crafted strings for your SQL queries, use prepared statements instead\\n\\n\`\`\`java\\nmyStmt = myCon.prepareStatement(\\"select * from students where age > ? and name = ?\\");\\nmyStmt.setInt(1, uri.getQueryParameter(\\"age\\"));\\nmyStmt.setString(2, uri.getQueryParameter(\\"name\\"));\\n\`\`\`\\n\\n## Resources\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_sqli", - "line_number": 32, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 32, - "end": 32, - "column": { - "start": 7, - "end": 54 - } - }, - "sink": { - "start": 32, - "end": 32, - "column": { - "start": 7, - "end": 54 - }, - "content": "emf.createEntityManager().createQuery(sqlQuery)" - }, - "parent_line_number": 32, - "snippet": "emf.createEntityManager().createQuery(sqlQuery)", - "fingerprint": "79d5d495c5c408c582b32582f1ae9171_2", - "old_fingerprint": "db6f664c606e5cc7e0b287583ab73e93_2", - "code_extract": " emf.createEntityManager().createQuery(sqlQuery);" - }, - { - "cwe_ids": [ - "89" - ], - "id": "java_lang_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n Statement stmt = conn.createStatement();\\n ResultSet rs = stmt.executeQuery(\\"select name from users where id='\\"+ uri.getQueryParameter(\\"user_id\\") \\"'\\")) {\\n\`\`\`\\n\\n✅ Instead of using dynamically crafted strings for your SQL queries, use prepared statements instead\\n\\n\`\`\`java\\nmyStmt = myCon.prepareStatement(\\"select * from students where age > ? and name = ?\\");\\nmyStmt.setInt(1, uri.getQueryParameter(\\"age\\"));\\nmyStmt.setString(2, uri.getQueryParameter(\\"name\\"));\\n\`\`\`\\n\\n## Resources\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_sqli", - "line_number": 36, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 36, - "end": 36, - "column": { - "start": 7, - "end": 65 - } - }, - "sink": { - "start": 36, - "end": 36, - "column": { - "start": 7, - "end": 65 - }, - "content": "x.prepareStatement(\\"select \\" + request.getParameter(\\"id\\"))" - }, - "parent_line_number": 36, - "snippet": "x.prepareStatement(\\"select \\" + request.getParameter(\\"id\\"))", - "fingerprint": "79d5d495c5c408c582b32582f1ae9171_3", - "old_fingerprint": "db6f664c606e5cc7e0b287583ab73e93_3", - "code_extract": " x.prepareStatement(\\"select \\" + request.getParameter(\\"id\\"));" - }, - { - "cwe_ids": [ - "89" - ], - "id": "java_lang_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n Statement stmt = conn.createStatement();\\n ResultSet rs = stmt.executeQuery(\\"select name from users where id='\\"+ uri.getQueryParameter(\\"user_id\\") \\"'\\")) {\\n\`\`\`\\n\\n✅ Instead of using dynamically crafted strings for your SQL queries, use prepared statements instead\\n\\n\`\`\`java\\nmyStmt = myCon.prepareStatement(\\"select * from students where age > ? and name = ?\\");\\nmyStmt.setInt(1, uri.getQueryParameter(\\"age\\"));\\nmyStmt.setString(2, uri.getQueryParameter(\\"name\\"));\\n\`\`\`\\n\\n## Resources\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_sqli", - "line_number": 40, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 40, - "end": 40, - "column": { - "start": 7, - "end": 61 - } - }, - "sink": { - "start": 40, - "end": 40, - "column": { - "start": 7, - "end": 61 - }, - "content": "x.executeQuery(\\"select \\" + request.getParameter(\\"id\\"))" - }, - "parent_line_number": 40, - "snippet": "x.executeQuery(\\"select \\" + request.getParameter(\\"id\\"))", - "fingerprint": "79d5d495c5c408c582b32582f1ae9171_4", - "old_fingerprint": "db6f664c606e5cc7e0b287583ab73e93_4", - "code_extract": " x.executeQuery(\\"select \\" + request.getParameter(\\"id\\"));" - }, - { - "cwe_ids": [ - "89" - ], - "id": "java_lang_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n Statement stmt = conn.createStatement();\\n ResultSet rs = stmt.executeQuery(\\"select name from users where id='\\"+ uri.getQueryParameter(\\"user_id\\") \\"'\\")) {\\n\`\`\`\\n\\n✅ Instead of using dynamically crafted strings for your SQL queries, use prepared statements instead\\n\\n\`\`\`java\\nmyStmt = myCon.prepareStatement(\\"select * from students where age > ? and name = ?\\");\\nmyStmt.setInt(1, uri.getQueryParameter(\\"age\\"));\\nmyStmt.setString(2, uri.getQueryParameter(\\"name\\"));\\n\`\`\`\\n\\n## Resources\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_sqli", - "line_number": 44, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 44, - "end": 44, - "column": { - "start": 7, - "end": 60 - } - }, - "sink": { - "start": 44, - "end": 44, - "column": { - "start": 7, - "end": 60 - }, - "content": "x.createQuery(\\"select \\" + request.getParameter(\\"id\\"))" - }, - "parent_line_number": 44, - "snippet": "x.createQuery(\\"select \\" + request.getParameter(\\"id\\"))", - "fingerprint": "79d5d495c5c408c582b32582f1ae9171_5", - "old_fingerprint": "db6f664c606e5cc7e0b287583ab73e93_5", - "code_extract": " x.createQuery(\\"select \\" + request.getParameter(\\"id\\"));" - } - ] -}" -`; - -exports[`java_lang_sqli safe 1`] = `"{}"`; diff --git a/tests/java/lang/sqli/test.js b/tests/java/lang/sqli/test.js index 25410b625..270d7df55 100644 --- a/tests/java/lang/sqli/test.js +++ b/tests/java/lang/sqli/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.java" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("safe", () => { - const testCase = "safe.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("safe", () => { + const testCase = "safe.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/sqli/testdata/bad.java b/tests/java/lang/sqli/testdata/bad.java index 2d6279ff8..55b57883a 100644 --- a/tests/java/lang/sqli/testdata/bad.java +++ b/tests/java/lang/sqli/testdata/bad.java @@ -16,6 +16,7 @@ public static void main() { // Open a connection try(Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); Statement stmt = conn.createStatement(); +// bearer:expected java_lang_sqli ResultSet rs = stmt.executeQuery(sqlQuery);) { // Extract data from result set while (rs.next()) { @@ -23,24 +24,29 @@ public static void main() { System.out.println(", Name: " + rs.getString("name")); } +// bearer:expected java_lang_sqli conn.prepareStatement(sqlQuery, 42); } catch (SQLException e) { e.printStackTrace(); } EntityManagerFactory emf=Persistence.createEntityManagerFactory("Student_details"); +// bearer:expected java_lang_sqli emf.createEntityManager().createQuery(sqlQuery); } public static void conTest(Connection x) { +// bearer:expected java_lang_sqli x.prepareStatement("select " + request.getParameter("id")); } public static void stmtTest(Statement x) { +// bearer:expected java_lang_sqli x.executeQuery("select " + request.getParameter("id")); } public static void emTest(EntityManager x) { +// bearer:expected java_lang_sqli x.createQuery("select " + request.getParameter("id")); } } diff --git a/tests/java/lang/trust_boundary_violation/__snapshots__/test.js.snap b/tests/java/lang/trust_boundary_violation/__snapshots__/test.js.snap deleted file mode 100644 index ac597bb2d..000000000 --- a/tests/java/lang/trust_boundary_violation/__snapshots__/test.js.snap +++ /dev/null @@ -1,418 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_trust_boundary_violation bad 1`] = ` -"{ - "warning": [ - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 5, - "end": 44 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 5, - "end": 44 - }, - "content": "constructor.setAttribute(KEY, getFoo())" - }, - "parent_line_number": 10, - "snippet": "constructor.setAttribute(KEY, getFoo())", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_0", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_0", - "code_extract": " constructor.setAttribute(KEY, getFoo());" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 16, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 16, - "end": 16, - "column": { - "start": 5, - "end": 33 - } - }, - "sink": { - "start": 16, - "end": 16, - "column": { - "start": 5, - "end": 33 - }, - "content": "param.setAttribute(KEY, foo)" - }, - "parent_line_number": 16, - "snippet": "param.setAttribute(KEY, foo)", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_1", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_1", - "code_extract": " param.setAttribute(KEY, foo);" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 17, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 17, - "end": 17, - "column": { - "start": 5, - "end": 37 - } - }, - "sink": { - "start": 17, - "end": 17, - "column": { - "start": 5, - "end": 37 - }, - "content": "param.setAttribute(foo, \\"value\\")" - }, - "parent_line_number": 17, - "snippet": "param.setAttribute(foo, \\"value\\")", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_2", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_2", - "code_extract": " param.setAttribute(foo, \\"value\\");" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 18, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 18, - "end": 18, - "column": { - "start": 5, - "end": 46 - } - }, - "sink": { - "start": 18, - "end": 18, - "column": { - "start": 5, - "end": 46 - }, - "content": "param.getSession().setAttribute(KEY, foo)" - }, - "parent_line_number": 18, - "snippet": "param.getSession().setAttribute(KEY, foo)", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_3", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_3", - "code_extract": " param.getSession().setAttribute(KEY, foo);" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 19, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 19, - "end": 19, - "column": { - "start": 5, - "end": 42 - } - }, - "sink": { - "start": 19, - "end": 19, - "column": { - "start": 5, - "end": 42 - }, - "content": "param.getSession().putValue(KEY, foo)" - }, - "parent_line_number": 19, - "snippet": "param.getSession().putValue(KEY, foo)", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_4", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_4", - "code_extract": " param.getSession().putValue(KEY, foo);" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 21, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 21, - "end": 21, - "column": { - "start": 5, - "end": 38 - } - }, - "sink": { - "start": 21, - "end": 21, - "column": { - "start": 5, - "end": 38 - }, - "content": "field.setAttribute(KEY, getFoo())" - }, - "parent_line_number": 21, - "snippet": "field.setAttribute(KEY, getFoo())", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_5", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_5", - "code_extract": " field.setAttribute(KEY, getFoo());" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 24, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 24, - "end": 24, - "column": { - "start": 5, - "end": 38 - } - }, - "sink": { - "start": 24, - "end": 24, - "column": { - "start": 5, - "end": 38 - }, - "content": "local.setAttribute(KEY, getFoo())" - }, - "parent_line_number": 24, - "snippet": "local.setAttribute(KEY, getFoo())", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_6", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_6", - "code_extract": " local.setAttribute(KEY, getFoo());" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 27, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 27, - "end": 27, - "column": { - "start": 5, - "end": 40 - } - }, - "sink": { - "start": 27, - "end": 27, - "column": { - "start": 5, - "end": 40 - }, - "content": "request.setAttribute(KEY, getFoo())" - }, - "parent_line_number": 27, - "snippet": "request.setAttribute(KEY, getFoo())", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_7", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_7", - "code_extract": " request.setAttribute(KEY, getFoo());" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 35, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 35, - "end": 35, - "column": { - "start": 7, - "end": 46 - } - }, - "sink": { - "start": 35, - "end": 35, - "column": { - "start": 7, - "end": 46 - }, - "content": "caughtError.setAttribute(KEY, getFoo())" - }, - "parent_line_number": 35, - "snippet": "caughtError.setAttribute(KEY, getFoo())", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_8", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_8", - "code_extract": " caughtError.setAttribute(KEY, getFoo());" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 41, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 41, - "end": 41, - "column": { - "start": 7, - "end": 54 - } - }, - "sink": { - "start": 41, - "end": 41, - "column": { - "start": 7, - "end": 54 - }, - "content": "caughtResourceError.setAttribute(KEY, getFoo())" - }, - "parent_line_number": 41, - "snippet": "caughtResourceError.setAttribute(KEY, getFoo())", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_9", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_9", - "code_extract": " caughtResourceError.setAttribute(KEY, getFoo());" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 45, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 45, - "end": 45, - "column": { - "start": 7, - "end": 43 - } - }, - "sink": { - "start": 45, - "end": 45, - "column": { - "start": 7, - "end": 43 - }, - "content": "resource.setAttribute(KEY, getFoo())" - }, - "parent_line_number": 45, - "snippet": "resource.setAttribute(KEY, getFoo())", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_10", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_10", - "code_extract": " resource.setAttribute(KEY, getFoo());" - }, - { - "cwe_ids": [ - "501" - ], - "id": "java_lang_trust_boundary_violation", - "title": "Usage of trusted and untrusted data inside the same data structure", - "description": "## Description\\n\\nMixing trusted and untrusted data inside the same data structure can lead\\nto untrusted data being mistakenly treated as being trusted.\\n\\n## Remediations\\n\\n✅ Avoid adding trusted data to data structures containing untrusted data\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_trust_boundary_violation", - "line_number": 49, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 49, - "end": 49, - "column": { - "start": 7, - "end": 42 - } - }, - "sink": { - "start": 49, - "end": 49, - "column": { - "start": 7, - "end": 42 - }, - "content": "forEach.setAttribute(KEY, getFoo())" - }, - "parent_line_number": 49, - "snippet": "forEach.setAttribute(KEY, getFoo())", - "fingerprint": "0011f9ce80042a297b7ed3b3edbcf26a_11", - "old_fingerprint": "f415451549d92e7d789365977c7a7ecd_11", - "code_extract": " forEach.setAttribute(KEY, getFoo());" - } - ] -}" -`; - -exports[`java_lang_trust_boundary_violation ok 1`] = `"{}"`; diff --git a/tests/java/lang/trust_boundary_violation/test.js b/tests/java/lang/trust_boundary_violation/test.js index 3c77c7b9d..e79f6c542 100644 --- a/tests/java/lang/trust_boundary_violation/test.js +++ b/tests/java/lang/trust_boundary_violation/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.java" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/trust_boundary_violation/testdata/bad.java b/tests/java/lang/trust_boundary_violation/testdata/bad.java index d64b4d2c8..35a0cddc9 100644 --- a/tests/java/lang/trust_boundary_violation/testdata/bad.java +++ b/tests/java/lang/trust_boundary_violation/testdata/bad.java @@ -7,23 +7,31 @@ public class Main { javax.servlet.ServletRequest field; public Main(HttpServletRequest constructor, String foo) throws ServletException { +// bearer:expected java_lang_trust_boundary_violation constructor.setAttribute(KEY, getFoo()); } public static void main(HttpServletRequest param) throws ServletException { var foo = getFoo(); +// bearer:expected java_lang_trust_boundary_violation param.setAttribute(KEY, foo); +// bearer:expected java_lang_trust_boundary_violation param.setAttribute(foo, "value"); +// bearer:expected java_lang_trust_boundary_violation param.getSession().setAttribute(KEY, foo); +// bearer:expected java_lang_trust_boundary_violation param.getSession().putValue(KEY, foo); +// bearer:expected java_lang_trust_boundary_violation field.setAttribute(KEY, getFoo()); javax.servlet.http.HttpServletRequest local = getReq(); +// bearer:expected java_lang_trust_boundary_violation local.setAttribute(KEY, getFoo()); // Fallback +// bearer:expected java_lang_trust_boundary_violation request.setAttribute(KEY, getFoo()); // This is contrived, but here to give full coverage of the shared instance rule @@ -32,20 +40,24 @@ public static void main(HttpServletRequest param) throws ServletException { } catch (SomeException e) { foo; } catch (OtherException|HttpServletRequest caughtError) { +// bearer:expected java_lang_trust_boundary_violation caughtError.setAttribute(KEY, getFoo()); } try (Something abc = getBar()) { abc.foo(); } catch (HttpServletRequest caughtResourceError) { +// bearer:expected java_lang_trust_boundary_violation caughtResourceError.setAttribute(KEY, getFoo()); } try (ServletRequest resource = getReq()) { +// bearer:expected java_lang_trust_boundary_violation resource.setAttribute(KEY, getFoo()); } for (ServletRequest forEach : getReqs()) { +// bearer:expected java_lang_trust_boundary_violation forEach.setAttribute(KEY, getFoo()); } } diff --git a/tests/java/lang/weak_hash_md5/__snapshots__/test.js.snap b/tests/java/lang/weak_hash_md5/__snapshots__/test.js.snap deleted file mode 100644 index 36a3c7956..000000000 --- a/tests/java/lang/weak_hash_md5/__snapshots__/test.js.snap +++ /dev/null @@ -1,86 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_weak_hash_md5 md5_hash 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "328" - ], - "id": "java_lang_weak_hash_md5", - "title": "Usage of weak hashing library (MD5)", - "description": "## Description\\n\\nA weak hashing library can lead to data breaches and greater security risk.\\n\\n## Remediations\\n\\nAccording to [OWASP](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/09-Testing_for_Weak_Cryptography/04-Testing_for_Weak_Encryption), MD5 is considered a weak hashing algorithms and therefore shouldn't be used.\\n\\n❌ Avoid libraries and algorithms with known weaknesses:\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"MD5\\");\\n\`\`\`\\n\\n✅ Use stronger encryption algorithms when storing data.\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"SHA-256\\");\\n\`\`\`\\n\\n## Resources\\n- [Java MessageDigest class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/MessageDigest.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_weak_hash_md5", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/md5_hash.java", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 6, - "end": 6, - "column": { - "start": 17, - "end": 30 - } - }, - "sink": { - "start": 6, - "end": 6, - "column": { - "start": 7, - "end": 42 - }, - "content": "md.update(user.fullname.getBytes())" - }, - "parent_line_number": 6, - "snippet": "md.update(user.fullname.getBytes())", - "fingerprint": "42ffc7b5d0492110367e370dc2e0752d_0", - "old_fingerprint": "64ccf1edbc2d451528f075885f51dd89_0", - "code_extract": " md.update(user.fullname.getBytes());" - } - ], - "high": [ - { - "cwe_ids": [ - "328" - ], - "id": "java_lang_weak_hash_md5", - "title": "Usage of weak hashing library (MD5)", - "description": "## Description\\n\\nA weak hashing library can lead to data breaches and greater security risk.\\n\\n## Remediations\\n\\nAccording to [OWASP](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/09-Testing_for_Weak_Cryptography/04-Testing_for_Weak_Encryption), MD5 is considered a weak hashing algorithms and therefore shouldn't be used.\\n\\n❌ Avoid libraries and algorithms with known weaknesses:\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"MD5\\");\\n\`\`\`\\n\\n✅ Use stronger encryption algorithms when storing data.\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"SHA-256\\");\\n\`\`\`\\n\\n## Resources\\n- [Java MessageDigest class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/MessageDigest.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_weak_hash_md5", - "line_number": 23, - "full_filename": "/tmp/bearer-scan/md5_hash.java", - "filename": ".", - "source": { - "start": 23, - "end": 23, - "column": { - "start": 7, - "end": 35 - } - }, - "sink": { - "start": 23, - "end": 23, - "column": { - "start": 7, - "end": 35 - }, - "content": "md.update(secret.getBytes())" - }, - "parent_line_number": 23, - "snippet": "md.update(secret.getBytes())", - "fingerprint": "42ffc7b5d0492110367e370dc2e0752d_1", - "old_fingerprint": "64ccf1edbc2d451528f075885f51dd89_1", - "code_extract": " md.update(secret.getBytes());" - } - ] -}" -`; diff --git a/tests/java/lang/weak_hash_md5/test.js b/tests/java/lang/weak_hash_md5/test.js index e732d3679..078d219e5 100644 --- a/tests/java/lang/weak_hash_md5/test.js +++ b/tests/java/lang/weak_hash_md5/test.js @@ -1,13 +1,20 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("md5_hash", () => { + const testCase = "md5_hash.java" + + const results = invoke(testCase) - test("md5_hash", () => { - const testCase = "md5_hash.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/weak_hash_md5/testdata/md5_hash.java b/tests/java/lang/weak_hash_md5/testdata/md5_hash.java index 66e3b8eda..a1911df96 100644 --- a/tests/java/lang/weak_hash_md5/testdata/md5_hash.java +++ b/tests/java/lang/weak_hash_md5/testdata/md5_hash.java @@ -3,6 +3,7 @@ public class HashFullname { public static void main(User user) { MessageDigest md = MessageDigest.getInstance("MD5"); +// bearer:expected java_lang_weak_hash_md5 md.update(user.fullname.getBytes()); byte[] digest = md.digest(); @@ -20,6 +21,7 @@ public static void main() { MessageDigest md = MessageDigest.getInstance("MD5"); String secret = SECRETS[new Random().nextInt(SECRETS.length)]; +// bearer:expected java_lang_weak_hash_md5 md.update(secret.getBytes()); byte[] digest = md.digest(); diff --git a/tests/java/lang/weak_hash_sha1/__snapshots__/test.js.snap b/tests/java/lang/weak_hash_sha1/__snapshots__/test.js.snap deleted file mode 100644 index 1b1813112..000000000 --- a/tests/java/lang/weak_hash_sha1/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_weak_hash_sha1 ok_sha_256 1`] = `"{}"`; - -exports[`java_lang_weak_hash_sha1 sha1_hash 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "328" - ], - "id": "java_lang_weak_hash_sha1", - "title": "Usage of weak hashing library (SHA-1)", - "description": "## Description\\n\\nA weak hashing library can lead to data breaches and greater security risk.\\n\\n## Remediations\\n\\nAccording to [OWASP](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/09-Testing_for_Weak_Cryptography/04-Testing_for_Weak_Encryption), SHA1 is considered a weak hashing algorithms and therefore shouldn't be used.\\n\\n❌ Avoid libraries and algorithms with known weaknesses:\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"SHA-1\\");\\n\`\`\`\\n\\n✅ Use stronger encryption algorithms when storing data.\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"SHA-256\\");\\n\`\`\`\\n\\n## Resources\\n- [Java MessageDigest class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/MessageDigest.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_weak_hash_sha1", - "line_number": 28, - "full_filename": "/tmp/bearer-scan/sha1_hash.java", - "filename": ".", - "source": { - "start": 28, - "end": 28, - "column": { - "start": 7, - "end": 35 - } - }, - "sink": { - "start": 28, - "end": 28, - "column": { - "start": 7, - "end": 35 - }, - "content": "md.update(secret.getBytes())" - }, - "parent_line_number": 28, - "snippet": "md.update(secret.getBytes())", - "fingerprint": "232a5bddb51183acc6620de96fcaa5b0_0", - "old_fingerprint": "08b0f560f7f3d808f7f19da3b6ba20f3_0", - "code_extract": " md.update(secret.getBytes());" - } - ] -}" -`; diff --git a/tests/java/lang/weak_hash_sha1/test.js b/tests/java/lang/weak_hash_sha1/test.js index 46169cea6..a8da29312 100644 --- a/tests/java/lang/weak_hash_sha1/test.js +++ b/tests/java/lang/weak_hash_sha1/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("ok_sha_256", () => { + const testCase = "ok_sha_256.java" + + const results = invoke(testCase) - test("ok_sha_256", () => { - const testCase = "ok_sha_256.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("sha1_hash", () => { - const testCase = "sha1_hash.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("sha1_hash", () => { + const testCase = "sha1_hash.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/weak_hash_sha1/testdata/sha1_hash.java b/tests/java/lang/weak_hash_sha1/testdata/sha1_hash.java index 5e3a4d58d..72708df8a 100644 --- a/tests/java/lang/weak_hash_sha1/testdata/sha1_hash.java +++ b/tests/java/lang/weak_hash_sha1/testdata/sha1_hash.java @@ -25,6 +25,7 @@ public String getSha1(HttpServletRequest request) { String secret = SECRETS[new Random().nextInt(SECRETS.length)]; MessageDigest md = MessageDigest.getInstance("SHA-1"); +// bearer:expected java_lang_weak_hash_sha1 md.update(secret.getBytes()); byte[] digest = md.digest(); sha1Hash = DatatypeConverter.printHexBinary(digest).toUpperCase(); diff --git a/tests/java/lang/weak_password_hash_md5/__snapshots__/test.js.snap b/tests/java/lang/weak_password_hash_md5/__snapshots__/test.js.snap deleted file mode 100644 index a55817d82..000000000 --- a/tests/java/lang/weak_password_hash_md5/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_weak_password_hash_md5 md5_hash 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "326" - ], - "id": "java_lang_weak_password_hash_md5", - "title": "Usage of weak hashing library on a password (MD5)", - "description": "## Description\\n\\nA weak hashing library can lead to data breaches and greater security risk.\\n\\n## Remediations\\n\\nAccording to [OWASP](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/09-Testing_for_Weak_Cryptography/04-Testing_for_Weak_Encryption), MD5 is considered a weak hashing algorithms and therefore shouldn't be used.\\n\\n❌ Avoid libraries and algorithms with known weaknesses:\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"MD5\\");\\n\`\`\`\\n\\n✅ Use stronger encryption algorithms when storing data.\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"SHA-256\\");\\n\`\`\`\\n\\n## Resources\\n- [Java MessageDigest class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/MessageDigest.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_weak_password_hash_md5", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/md5_hash.java", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 17, - "end": 33 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 7, - "end": 45 - }, - "content": "md.update(user.newPassword.getBytes())" - }, - "parent_line_number": 5, - "snippet": "md.update(user.newPassword.getBytes())", - "fingerprint": "5bdda7c35f0837f7f2dbb73d6b20f32c_0", - "old_fingerprint": "ce1c913ba6a62cdeffc141ced5c96b5a_0", - "code_extract": " md.update(user.newPassword.getBytes());" - } - ] -}" -`; - -exports[`java_lang_weak_password_hash_md5 ok_not_a_password 1`] = `"{}"`; diff --git a/tests/java/lang/weak_password_hash_md5/test.js b/tests/java/lang/weak_password_hash_md5/test.js index ac08c84a1..dc53bf7f0 100644 --- a/tests/java/lang/weak_password_hash_md5/test.js +++ b/tests/java/lang/weak_password_hash_md5/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("md5_hash", () => { + const testCase = "md5_hash.java" + + const results = invoke(testCase) - test("md5_hash", () => { - const testCase = "md5_hash.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_not_a_password", () => { - const testCase = "ok_not_a_password.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_not_a_password", () => { + const testCase = "ok_not_a_password.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/weak_password_hash_md5/testdata/md5_hash.java b/tests/java/lang/weak_password_hash_md5/testdata/md5_hash.java index 71819726a..4e57bd4e1 100644 --- a/tests/java/lang/weak_password_hash_md5/testdata/md5_hash.java +++ b/tests/java/lang/weak_password_hash_md5/testdata/md5_hash.java @@ -2,6 +2,7 @@ public class HashPassword { public static void main(User user) { java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); +// bearer:expected java_lang_weak_password_hash_md5 md.update(user.newPassword.getBytes()); byte[] digest = md.digest(); diff --git a/tests/java/lang/weak_password_hash_sha1/__snapshots__/test.js.snap b/tests/java/lang/weak_password_hash_sha1/__snapshots__/test.js.snap deleted file mode 100644 index 09e192fc3..000000000 --- a/tests/java/lang/weak_password_hash_sha1/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_weak_password_hash_sha1 ok_not_a_password 1`] = `"{}"`; - -exports[`java_lang_weak_password_hash_sha1 sha1_hash 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "326" - ], - "id": "java_lang_weak_password_hash_sha1", - "title": "Usage of weak hashing library on a password (SHA1)", - "description": "## Description\\n\\nA weak hashing library can lead to data breaches and greater security risk.\\n\\n## Remediations\\n\\nAccording to [OWASP](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/09-Testing_for_Weak_Cryptography/04-Testing_for_Weak_Encryption), SHA1 is considered a weak hashing algorithms and therefore shouldn't be used.\\n\\n❌ Avoid libraries and algorithms with known weaknesses:\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"SHA-1\\");\\n\`\`\`\\n\\n✅ Use stronger encryption algorithms when storing data.\\n\\n\`\`\`java\\n MessageDigest md = MessageDigest.getInstance(\\"SHA-256\\");\\n\`\`\`\\n\\n## Resources\\n- [Java MessageDigest class](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/MessageDigest.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_weak_password_hash_sha1", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/sha1_hash.java", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 7, - "end": 7, - "column": { - "start": 17, - "end": 33 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 7, - "end": 45 - }, - "content": "md.update(user.newPassword.getBytes())" - }, - "parent_line_number": 7, - "snippet": "md.update(user.newPassword.getBytes())", - "fingerprint": "a854846829baea6ec276e7f5d1f1b227_0", - "old_fingerprint": "4da276b14151bc147141492073f8756a_0", - "code_extract": " md.update(user.newPassword.getBytes());" - } - ] -}" -`; diff --git a/tests/java/lang/weak_password_hash_sha1/test.js b/tests/java/lang/weak_password_hash_sha1/test.js index 47d2a115a..c5634aca4 100644 --- a/tests/java/lang/weak_password_hash_sha1/test.js +++ b/tests/java/lang/weak_password_hash_sha1/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("ok_not_a_password", () => { + const testCase = "ok_not_a_password.java" + + const results = invoke(testCase) - test("ok_not_a_password", () => { - const testCase = "ok_not_a_password.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("sha1_hash", () => { - const testCase = "sha1_hash.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("sha1_hash", () => { + const testCase = "sha1_hash.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/weak_password_hash_sha1/testdata/sha1_hash.java b/tests/java/lang/weak_password_hash_sha1/testdata/sha1_hash.java index 53dd6910a..46fbb9a13 100644 --- a/tests/java/lang/weak_password_hash_sha1/testdata/sha1_hash.java +++ b/tests/java/lang/weak_password_hash_sha1/testdata/sha1_hash.java @@ -4,6 +4,7 @@ public class HashPassword { public static void main(User user) { MessageDigest md = MessageDigest.getInstance("SHA-1"); +// bearer:expected java_lang_weak_password_hash_sha1 md.update(user.newPassword.getBytes()); byte[] digest = md.digest(); diff --git a/tests/java/lang/xpath_injection/__snapshots__/test.js.snap b/tests/java/lang/xpath_injection/__snapshots__/test.js.snap deleted file mode 100644 index 4604513e3..000000000 --- a/tests/java/lang/xpath_injection/__snapshots__/test.js.snap +++ /dev/null @@ -1,76 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_xpath_injection xpath_injection 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "643" - ], - "id": "java_lang_xpath_injection", - "title": "Unsanitized user input in XPath", - "description": "## Description\\n Unsanitized input going into XPath evaluate detected.\\n This could lead to xpath injection if variables passed into the evaluate or compile commands are not properly sanitized.\\n Xpath injection could lead to unauthorized access to sensitive information in XML documents.\\n Instead, thoroughly sanitize user input or use parameterized xpath queries if you can.\\n\\n## Remediations\\n\\n✅ Sanitize XPATH queries\\n\\n\`\`\`java\\n public class Cls extends HttpServlet\\n {\\n\\n public void handleRequest(HttpServletRequest request, HttpServletResponse response)\\n {\\n String userID = request.getParameter(\\"userID\\");\\n String sanitizedUserID = sanitize(userID);\\n\\n javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance();\\n javax.xml.xpath.XPath xp = xpf.newXPath();\\n\\n String expression = \\"/Users/User[@userID='\\" + sanitizedUserID + \\"']\\";\\n String result = xp.evaluate(expression, xmlDocument);\\n }\\n }\\n\`\`\`\\n\\n## References\\n- [XPATH Injection](https://owasp.org/www-community/attacks/XPATH_Injection)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_xpath_injection", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/xpath_injection.java", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 25, - "end": 61 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 25, - "end": 61 - }, - "content": "xp.evaluate(expression, xmlDocument)" - }, - "parent_line_number": 12, - "snippet": "xp.evaluate(expression, xmlDocument)", - "fingerprint": "d8456dfb1c7f1ed1b1c088e426430687_0", - "old_fingerprint": "a1c9a49efc8e4e79a8407bbb5e677663_0", - "code_extract": " String result = xp.evaluate(expression, xmlDocument);" - }, - { - "cwe_ids": [ - "643" - ], - "id": "java_lang_xpath_injection", - "title": "Unsanitized user input in XPath", - "description": "## Description\\n Unsanitized input going into XPath evaluate detected.\\n This could lead to xpath injection if variables passed into the evaluate or compile commands are not properly sanitized.\\n Xpath injection could lead to unauthorized access to sensitive information in XML documents.\\n Instead, thoroughly sanitize user input or use parameterized xpath queries if you can.\\n\\n## Remediations\\n\\n✅ Sanitize XPATH queries\\n\\n\`\`\`java\\n public class Cls extends HttpServlet\\n {\\n\\n public void handleRequest(HttpServletRequest request, HttpServletResponse response)\\n {\\n String userID = request.getParameter(\\"userID\\");\\n String sanitizedUserID = sanitize(userID);\\n\\n javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance();\\n javax.xml.xpath.XPath xp = xpf.newXPath();\\n\\n String expression = \\"/Users/User[@userID='\\" + sanitizedUserID + \\"']\\";\\n String result = xp.evaluate(expression, xmlDocument);\\n }\\n }\\n\`\`\`\\n\\n## References\\n- [XPATH Injection](https://owasp.org/www-community/attacks/XPATH_Injection)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_xpath_injection", - "line_number": 14, - "full_filename": "/tmp/bearer-scan/xpath_injection.java", - "filename": ".", - "source": { - "start": 14, - "end": 14, - "column": { - "start": 24, - "end": 58 - } - }, - "sink": { - "start": 14, - "end": 14, - "column": { - "start": 24, - "end": 58 - }, - "content": "xpf.newXPath().compile(expression)" - }, - "parent_line_number": 14, - "snippet": "xpf.newXPath().compile(expression)", - "fingerprint": "d8456dfb1c7f1ed1b1c088e426430687_1", - "old_fingerprint": "a1c9a49efc8e4e79a8407bbb5e677663_1", - "code_extract": " var compiled = xpf.newXPath().compile(expression);" - } - ] -}" -`; diff --git a/tests/java/lang/xpath_injection/test.js b/tests/java/lang/xpath_injection/test.js index f8dfcab60..7d10eaea3 100644 --- a/tests/java/lang/xpath_injection/test.js +++ b/tests/java/lang/xpath_injection/test.js @@ -1,13 +1,20 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("xpath_injection", () => { + const testCase = "xpath_injection.java" + + const results = invoke(testCase) - test("xpath_injection", () => { - const testCase = "xpath_injection.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/xpath_injection/testdata/xpath_injection.java b/tests/java/lang/xpath_injection/testdata/xpath_injection.java index e7dfed6ab..d1b07fc30 100644 --- a/tests/java/lang/xpath_injection/testdata/xpath_injection.java +++ b/tests/java/lang/xpath_injection/testdata/xpath_injection.java @@ -9,8 +9,10 @@ public void handleRequest(HttpServletRequest request, HttpServletResponse respon javax.xml.xpath.XPath xp = xpf.newXPath(); String expression = "/Users/User[@userID='" + userID + "']"; +// bearer:expected java_lang_xpath_injection String result = xp.evaluate(expression, xmlDocument); +// bearer:expected java_lang_xpath_injection var compiled = xpf.newXPath().compile(expression); } } diff --git a/tests/java/lang/xss_response_writer/__snapshots__/test.js.snap b/tests/java/lang/xss_response_writer/__snapshots__/test.js.snap deleted file mode 100644 index a8e481de0..000000000 --- a/tests/java/lang/xss_response_writer/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_lang_xss_response_writer ok 1`] = `"{}"`; - -exports[`java_lang_xss_response_writer vulnerable 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "79" - ], - "id": "java_lang_xss_response_writer", - "title": "Unsanitized user input in output stream (XSS)", - "description": "## Description\\n\\nMake sure to encode and sanitize any user input before passing it down to \`response.getWriter()\` to avoid cross-site scripting (XSS) attacks.\\n\\n✅ Use an encoder to minimize XSS risk\\n\\n\`\`\`java\\n String userInput = req.getQueryString(\\"user\\");\\n String encodedUserInput = Encode.forHtml(userInput)\\n response.getWriter().write(encodedUserInput)\\n\`\`\`\\n\\n✅ Even better, sanitize user input\\n\\n\`\`\`java\\n String userInput = req.getQueryString(\\"user\\");\\n String sanitizedUserInput = sanitize(userInput);\\n response.getWriter().write(sanitizedUserInput);\\n\`\`\`\\n\\n## Resources\\n\\n- [OWASP XSS Prevention Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n- [OWASP Java Encoder](https://owasp.org/www-project-java-encoder/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_lang_xss_response_writer", - "line_number": 14, - "full_filename": "/tmp/bearer-scan/vulnerable.java", - "filename": ".", - "source": { - "start": 14, - "end": 14, - "column": { - "start": 7, - "end": 24 - } - }, - "sink": { - "start": 14, - "end": 14, - "column": { - "start": 7, - "end": 24 - }, - "content": "out.println(user)" - }, - "parent_line_number": 14, - "snippet": "out.println(user)", - "fingerprint": "32b949b64f3ce7cf97466aa83aae561a_0", - "old_fingerprint": "4dd9cda869eb830ac4340c82e1084f03_0", - "code_extract": " out.println(user);" - } - ] -}" -`; diff --git a/tests/java/lang/xss_response_writer/test.js b/tests/java/lang/xss_response_writer/test.js index d644c4a78..706fbe092 100644 --- a/tests/java/lang/xss_response_writer/test.js +++ b/tests/java/lang/xss_response_writer/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("ok", () => { + const testCase = "ok.java" + + const results = invoke(testCase) - test("ok", () => { - const testCase = "ok.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("vulnerable", () => { - const testCase = "vulnerable.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("vulnerable", () => { + const testCase = "vulnerable.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/lang/xss_response_writer/testdata/vulnerable.java b/tests/java/lang/xss_response_writer/testdata/vulnerable.java index 9164775d6..04de457b2 100644 --- a/tests/java/lang/xss_response_writer/testdata/vulnerable.java +++ b/tests/java/lang/xss_response_writer/testdata/vulnerable.java @@ -11,6 +11,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) { // Actual logic goes here. PrintWriter out = response.getWriter(); String user = request.getQueryString("user"); +// bearer:expected java_lang_xss_response_writer out.println(user); } diff --git a/tests/java/spring/sqli/__snapshots__/test.js.snap b/tests/java/spring/sqli/__snapshots__/test.js.snap deleted file mode 100644 index 062b27cd1..000000000 --- a/tests/java/spring/sqli/__snapshots__/test.js.snap +++ /dev/null @@ -1,146 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`java_spring_sqli bad 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "89" - ], - "id": "java_spring_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n String query = \\"update user set name='\\"+uri.getQueryParameter(\\"name\\")+\\"' where id='\\"+uri.getQueryParameter(\\"userId\\")+\\"'\\";\\n return jdbcTemplate.update(query);\\n\`\`\`\\n\\n✅ Use \`PreparedStatement\` creators and setters to construct SQL queries\\n\\n\`\`\`java\\nnew PreparedStatementCreator() {\\n public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {\\n String updateString = \\"update user set name = ? where id = ?\\";\\n return conn.prepareStatement(updateString);\\n }\\n}\\n\\nnew PreparedStatementSetter() {\\n public void setValues(PreparedStatement preparedStatement) throws SQLException {\\n preparedStatement.setString(1, uri.getQueryParameter(\\"name\\"))\\n preparedStatement.setInt(2, uri.getQueryParameter(\\"userId\\"))\\n }\\n}\\n\`\`\`\\n\\n## Resources\\n- [JDBC Template class](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html)\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_spring_sqli", - "line_number": 14, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 14, - "end": 14, - "column": { - "start": 21, - "end": 83 - } - }, - "sink": { - "start": 14, - "end": 14, - "column": { - "start": 21, - "end": 83 - }, - "content": "new PreparedStatementCreatorFactory(myQueryStr, Types.VARCHAR)" - }, - "parent_line_number": 14, - "snippet": "new PreparedStatementCreatorFactory(myQueryStr, Types.VARCHAR)", - "fingerprint": "ebf8b9a53c73eabed841989514b90054_0", - "old_fingerprint": "9ea5f5b3d1131ed66c9e6fe7484aa506_0", - "code_extract": " var factory = new PreparedStatementCreatorFactory(myQueryStr, Types.VARCHAR);" - }, - { - "cwe_ids": [ - "89" - ], - "id": "java_spring_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n String query = \\"update user set name='\\"+uri.getQueryParameter(\\"name\\")+\\"' where id='\\"+uri.getQueryParameter(\\"userId\\")+\\"'\\";\\n return jdbcTemplate.update(query);\\n\`\`\`\\n\\n✅ Use \`PreparedStatement\` creators and setters to construct SQL queries\\n\\n\`\`\`java\\nnew PreparedStatementCreator() {\\n public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {\\n String updateString = \\"update user set name = ? where id = ?\\";\\n return conn.prepareStatement(updateString);\\n }\\n}\\n\\nnew PreparedStatementSetter() {\\n public void setValues(PreparedStatement preparedStatement) throws SQLException {\\n preparedStatement.setString(1, uri.getQueryParameter(\\"name\\"))\\n preparedStatement.setInt(2, uri.getQueryParameter(\\"userId\\"))\\n }\\n}\\n\`\`\`\\n\\n## Resources\\n- [JDBC Template class](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html)\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_spring_sqli", - "line_number": 15, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 15, - "end": 15, - "column": { - "start": 7, - "end": 58 - } - }, - "sink": { - "start": 15, - "end": 15, - "column": { - "start": 7, - "end": 58 - }, - "content": "factory.newPreparedStatementCreator(myQueryStr, [])" - }, - "parent_line_number": 15, - "snippet": "factory.newPreparedStatementCreator(myQueryStr, [])", - "fingerprint": "ebf8b9a53c73eabed841989514b90054_1", - "old_fingerprint": "9ea5f5b3d1131ed66c9e6fe7484aa506_1", - "code_extract": " factory.newPreparedStatementCreator(myQueryStr, []);" - }, - { - "cwe_ids": [ - "89" - ], - "id": "java_spring_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n String query = \\"update user set name='\\"+uri.getQueryParameter(\\"name\\")+\\"' where id='\\"+uri.getQueryParameter(\\"userId\\")+\\"'\\";\\n return jdbcTemplate.update(query);\\n\`\`\`\\n\\n✅ Use \`PreparedStatement\` creators and setters to construct SQL queries\\n\\n\`\`\`java\\nnew PreparedStatementCreator() {\\n public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {\\n String updateString = \\"update user set name = ? where id = ?\\";\\n return conn.prepareStatement(updateString);\\n }\\n}\\n\\nnew PreparedStatementSetter() {\\n public void setValues(PreparedStatement preparedStatement) throws SQLException {\\n preparedStatement.setString(1, uri.getQueryParameter(\\"name\\"))\\n preparedStatement.setInt(2, uri.getQueryParameter(\\"userId\\"))\\n }\\n}\\n\`\`\`\\n\\n## Resources\\n- [JDBC Template class](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html)\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_spring_sqli", - "line_number": 17, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 17, - "end": 17, - "column": { - "start": 7, - "end": 38 - } - }, - "sink": { - "start": 17, - "end": 17, - "column": { - "start": 7, - "end": 38 - }, - "content": "t.batchUpdate(\\"ok\\", myQueryStr)" - }, - "parent_line_number": 17, - "snippet": "t.batchUpdate(\\"ok\\", myQueryStr)", - "fingerprint": "ebf8b9a53c73eabed841989514b90054_2", - "old_fingerprint": "9ea5f5b3d1131ed66c9e6fe7484aa506_2", - "code_extract": " t.batchUpdate(\\"ok\\", myQueryStr);" - }, - { - "cwe_ids": [ - "89" - ], - "id": "java_spring_sqli", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\n\\nIncluding unsanitized data, such as user input or request data, in raw SQL\\nqueries makes your application vulnerable to SQL injection attacks.\\n\\n## Remediations\\n\\n❌ Avoid raw queries, especially those that contain unsanitized user input:\\n\\n\`\`\`java\\n String query = \\"update user set name='\\"+uri.getQueryParameter(\\"name\\")+\\"' where id='\\"+uri.getQueryParameter(\\"userId\\")+\\"'\\";\\n return jdbcTemplate.update(query);\\n\`\`\`\\n\\n✅ Use \`PreparedStatement\` creators and setters to construct SQL queries\\n\\n\`\`\`java\\nnew PreparedStatementCreator() {\\n public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {\\n String updateString = \\"update user set name = ? where id = ?\\";\\n return conn.prepareStatement(updateString);\\n }\\n}\\n\\nnew PreparedStatementSetter() {\\n public void setValues(PreparedStatement preparedStatement) throws SQLException {\\n preparedStatement.setString(1, uri.getQueryParameter(\\"name\\"))\\n preparedStatement.setInt(2, uri.getQueryParameter(\\"userId\\"))\\n }\\n}\\n\`\`\`\\n\\n## Resources\\n- [JDBC Template class](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html)\\n- [OWASP SQL injection explained](https://owasp.org/www-community/attacks/SQL_Injection)\\n- [OWASP SQL injection prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/java_spring_sqli", - "line_number": 18, - "full_filename": "/tmp/bearer-scan/bad.java", - "filename": ".", - "source": { - "start": 18, - "end": 18, - "column": { - "start": 7, - "end": 28 - } - }, - "sink": { - "start": 18, - "end": 18, - "column": { - "start": 7, - "end": 28 - }, - "content": "t.execute(myQueryStr)" - }, - "parent_line_number": 18, - "snippet": "t.execute(myQueryStr)", - "fingerprint": "ebf8b9a53c73eabed841989514b90054_3", - "old_fingerprint": "9ea5f5b3d1131ed66c9e6fe7484aa506_3", - "code_extract": " t.execute(myQueryStr);" - } - ] -}" -`; - -exports[`java_spring_sqli safe 1`] = `"{}"`; diff --git a/tests/java/spring/sqli/test.js b/tests/java/spring/sqli/test.js index 25410b625..270d7df55 100644 --- a/tests/java/spring/sqli/test.js +++ b/tests/java/spring/sqli/test.js @@ -1,19 +1,30 @@ -const { createInvoker, getEnvironment } = require("../../../helper.js") +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.java" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("safe", () => { - const testCase = "safe.java" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("safe", () => { + const testCase = "safe.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/java/spring/sqli/testdata/bad.java b/tests/java/spring/sqli/testdata/bad.java index 14461f9b0..d6f81a164 100644 --- a/tests/java/spring/sqli/testdata/bad.java +++ b/tests/java/spring/sqli/testdata/bad.java @@ -11,10 +11,14 @@ public class Foo { public void updateUser() { String myQueryStr = "update user set name='"+request.getParameter("name")+"' where id='"+request.getParameter("userId")+"'"; +// bearer:expected java_spring_sqli var factory = new PreparedStatementCreatorFactory(myQueryStr, Types.VARCHAR); +// bearer:expected java_spring_sqli factory.newPreparedStatementCreator(myQueryStr, []); +// bearer:expected java_spring_sqli t.batchUpdate("ok", myQueryStr); +// bearer:expected java_spring_sqli t.execute(myQueryStr); } }