diff --git a/scripts/migrate_tests.js b/scripts/migrate_tests.js index 44757f2d4..d757cdbf9 100644 --- a/scripts/migrate_tests.js +++ b/scripts/migrate_tests.js @@ -41,7 +41,7 @@ const determine_annotations = (rule, outputs) => { const write_annoation = (filePath, result) => { let lines = fs.readFileSync(filePath, 'utf8').split('\n'); - lines.splice(result.line_number - 1, 0, `# bearer:expected ${result.id}`); + lines.splice(result.line_number - 1, 0, `// bearer:expected ${result.id}`); fs.writeFileSync(filePath, lines.join('\n')); } diff --git a/tests/javascript/express/cross_site_scripting/__snapshots__/test.js.snap b/tests/javascript/express/cross_site_scripting/__snapshots__/test.js.snap deleted file mode 100644 index 81792ed2b..000000000 --- a/tests/javascript/express/cross_site_scripting/__snapshots__/test.js.snap +++ /dev/null @@ -1,534 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_cross_site_scripting no_xss 1`] = `"{}"`; - -exports[`javascript_express_cross_site_scripting res_send_xss 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/res_send_xss.js", - "filename": ".", - "source": { - "start": 9, - "end": 9, - "column": { - "start": 3, - "end": 52 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 3, - "end": 52 - }, - "content": "res.send(\\"

\\" + req.body.customer.name + \\"

\\")" - }, - "parent_line_number": 9, - "snippet": "res.send(\\"

\\" + req.body.customer.name + \\"

\\")", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_0", - "old_fingerprint": "4ba7bacee2b0774a580d15c60551c11f_0", - "code_extract": " res.send(\\"

\\" + req.body.customer.name + \\"

\\")" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 13, - "full_filename": "/tmp/bearer-scan/res_send_xss.js", - "filename": ".", - "source": { - "start": 13, - "end": 13, - "column": { - "start": 3, - "end": 49 - } - }, - "sink": { - "start": 13, - "end": 13, - "column": { - "start": 3, - "end": 49 - }, - "content": "res.send(\\"

\\" + req.body[\\"user_id\\"] + \\"

\\")" - }, - "parent_line_number": 13, - "snippet": "res.send(\\"

\\" + req.body[\\"user_id\\"] + \\"

\\")", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_1", - "old_fingerprint": "4ba7bacee2b0774a580d15c60551c11f_1", - "code_extract": " res.send(\\"

\\" + req.body[\\"user_id\\"] + \\"

\\")" - } - ] -}" -`; - -exports[`javascript_express_cross_site_scripting res_write_xss 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/res_write_xss.js", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 56 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 56 - }, - "content": "res.write(\\"

Greetings \\" + customerName + \\"

\\")" - }, - "parent_line_number": 10, - "snippet": "res.write(\\"

Greetings \\" + customerName + \\"

\\")", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_0", - "old_fingerprint": "acf04397b0418a725db9d537ac99b39a_0", - "code_extract": " res.write(\\"

Greetings \\" + customerName + \\"

\\")" - } - ] -}" -`; - -exports[`javascript_express_cross_site_scripting user_input_types 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 26 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 26 - }, - "content": "res.send(req.params.oops)" - }, - "parent_line_number": 3, - "snippet": "res.send(req.params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_0", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_0", - "code_extract": "res.send(req.params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 9, - "end": 9, - "column": { - "start": 1, - "end": 22 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 1, - "end": 22 - }, - "content": "res.send(params.oops)" - }, - "parent_line_number": 9, - "snippet": "res.send(params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_1", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_1", - "code_extract": "res.send(params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 1, - "end": 15 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 1, - "end": 15 - }, - "content": "res.send(oops)" - }, - "parent_line_number": 10, - "snippet": "res.send(oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_2", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_2", - "code_extract": "res.send(oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 13, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 13, - "end": 13, - "column": { - "start": 1, - "end": 26 - } - }, - "sink": { - "start": 13, - "end": 13, - "column": { - "start": 1, - "end": 26 - }, - "content": "res.send(foo.params.oops)" - }, - "parent_line_number": 13, - "snippet": "res.send(foo.params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_3", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_3", - "code_extract": "res.send(foo.params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 16, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 16, - "end": 16, - "column": { - "start": 3, - "end": 29 - } - }, - "sink": { - "start": 16, - "end": 16, - "column": { - "start": 3, - "end": 29 - }, - "content": "res.send(foo2.params.oops)" - }, - "parent_line_number": 16, - "snippet": "res.send(foo2.params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_4", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_4", - "code_extract": " res.send(foo2.params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 17, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 17, - "end": 17, - "column": { - "start": 3, - "end": 24 - } - }, - "sink": { - "start": 17, - "end": 17, - "column": { - "start": 3, - "end": 24 - }, - "content": "res.send(params.oops)" - }, - "parent_line_number": 17, - "snippet": "res.send(params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_5", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_5", - "code_extract": " res.send(params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 21, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 21, - "end": 21, - "column": { - "start": 3, - "end": 29 - } - }, - "sink": { - "start": 21, - "end": 21, - "column": { - "start": 3, - "end": 29 - }, - "content": "res.send(foo3.params.oops)" - }, - "parent_line_number": 21, - "snippet": "res.send(foo3.params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_6", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_6", - "code_extract": " res.send(foo3.params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 22, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 22, - "end": 22, - "column": { - "start": 3, - "end": 24 - } - }, - "sink": { - "start": 22, - "end": 22, - "column": { - "start": 3, - "end": 24 - }, - "content": "res.send(params.oops)" - }, - "parent_line_number": 22, - "snippet": "res.send(params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_7", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_7", - "code_extract": " res.send(params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 26, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 26, - "end": 26, - "column": { - "start": 3, - "end": 29 - } - }, - "sink": { - "start": 26, - "end": 26, - "column": { - "start": 3, - "end": 29 - }, - "content": "res.send(foo4.params.oops)" - }, - "parent_line_number": 26, - "snippet": "res.send(foo4.params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_8", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_8", - "code_extract": " res.send(foo4.params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 27, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 27, - "end": 27, - "column": { - "start": 3, - "end": 24 - } - }, - "sink": { - "start": 27, - "end": 27, - "column": { - "start": 3, - "end": 24 - }, - "content": "res.send(params.oops)" - }, - "parent_line_number": 27, - "snippet": "res.send(params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_9", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_9", - "code_extract": " res.send(params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 33, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 33, - "end": 33, - "column": { - "start": 5, - "end": 31 - } - }, - "sink": { - "start": 33, - "end": 33, - "column": { - "start": 5, - "end": 31 - }, - "content": "res.send(foo5.params.oops)" - }, - "parent_line_number": 33, - "snippet": "res.send(foo5.params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_10", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_10", - "code_extract": " res.send(foo5.params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_express_cross_site_scripting", - "title": "Unsanitized user input in HTTP response (XSS)", - "description": "## Description\\nSending unsanitized user input in a response puts your application at risk of cross-site scripting attacks.\\n\\n\\n## Remediations\\n❌ Avoid including user input directly in a response:\\n\\n\`\`\`javascript\\nres.send(req.body.data)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_cross_site_scripting", - "line_number": 34, - "full_filename": "/tmp/bearer-scan/user_input_types.ts", - "filename": ".", - "source": { - "start": 34, - "end": 34, - "column": { - "start": 5, - "end": 26 - } - }, - "sink": { - "start": 34, - "end": 34, - "column": { - "start": 5, - "end": 26 - }, - "content": "res.send(params.oops)" - }, - "parent_line_number": 34, - "snippet": "res.send(params.oops)", - "fingerprint": "df7c00dff42ea03e2153d41a4dc2fc8e_11", - "old_fingerprint": "8294bf109e23715233663d5f51e4954a_11", - "code_extract": " res.send(params.oops)" - } - ] -}" -`; diff --git a/tests/javascript/express/cross_site_scripting/test.js b/tests/javascript/express/cross_site_scripting/test.js index cd70f9b3a..db84c1cc8 100644 --- a/tests/javascript/express/cross_site_scripting/test.js +++ b/tests/javascript/express/cross_site_scripting/test.js @@ -1,31 +1,50 @@ -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("no_xss", () => { + const testCase = "no_xss.js" + + const results = invoke(testCase) - test("no_xss", () => { - const testCase = "no_xss.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("res_send_xss", () => { - const testCase = "res_send_xss.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("res_send_xss", () => { + const testCase = "res_send_xss.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("res_write_xss", () => { - const testCase = "res_write_xss.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("res_write_xss", () => { + const testCase = "res_write_xss.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("user_input_types", () => { - const testCase = "user_input_types.ts" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("user_input_types", () => { + const testCase = "user_input_types.ts" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/cross_site_scripting/testdata/res_send_xss.js b/tests/javascript/express/cross_site_scripting/testdata/res_send_xss.js index 53d568d95..5ca517025 100644 --- a/tests/javascript/express/cross_site_scripting/testdata/res_send_xss.js +++ b/tests/javascript/express/cross_site_scripting/testdata/res_send_xss.js @@ -6,9 +6,11 @@ app.use(helmet()) app.use(helmet.hidePoweredBy()) app.get("/bad", (req, res) => { +// bearer:expected javascript_express_cross_site_scripting res.send("

" + req.body.customer.name + "

") }) app.get("/bad-2", (req, res) => { +// bearer:expected javascript_express_cross_site_scripting res.send("

" + req.body["user_id"] + "

") }) diff --git a/tests/javascript/express/cross_site_scripting/testdata/res_write_xss.js b/tests/javascript/express/cross_site_scripting/testdata/res_write_xss.js index d72e4d29a..d023834e3 100644 --- a/tests/javascript/express/cross_site_scripting/testdata/res_write_xss.js +++ b/tests/javascript/express/cross_site_scripting/testdata/res_write_xss.js @@ -7,5 +7,6 @@ app.use(helmet.hidePoweredBy()) app.get("/bad", (req, res) => { var customerName = req.body.customer.name +// bearer:expected javascript_express_cross_site_scripting res.write("

Greetings " + customerName + "

") }) diff --git a/tests/javascript/express/cross_site_scripting/testdata/user_input_types.ts b/tests/javascript/express/cross_site_scripting/testdata/user_input_types.ts index 02c809503..7679d0780 100644 --- a/tests/javascript/express/cross_site_scripting/testdata/user_input_types.ts +++ b/tests/javascript/express/cross_site_scripting/testdata/user_input_types.ts @@ -1,36 +1,48 @@ // This file is indirectly testing javascript_shared_express_user_input +// bearer:expected javascript_express_cross_site_scripting res.send(req.params.oops) let { params } = req let { oops } = params let { subOops } = oops +// bearer:expected javascript_express_cross_site_scripting res.send(params.oops) +// bearer:expected javascript_express_cross_site_scripting res.send(oops) const foo: Request = x +// bearer:expected javascript_express_cross_site_scripting res.send(foo.params.oops) const f = (x: string, foo2: Request, { params }: Request) => { +// bearer:expected javascript_express_cross_site_scripting res.send(foo2.params.oops) +// bearer:expected javascript_express_cross_site_scripting res.send(params.oops) } function(foo3: Request, { params }: Request) { +// bearer:expected javascript_express_cross_site_scripting res.send(foo3.params.oops) +// bearer:expected javascript_express_cross_site_scripting res.send(params.oops) } function f2(foo4: Request, { params }: Request) { +// bearer:expected javascript_express_cross_site_scripting res.send(foo4.params.oops) +// bearer:expected javascript_express_cross_site_scripting res.send(params.oops) } class X extends Y { m(foo5: Request, { params }: Request) { +// bearer:expected javascript_express_cross_site_scripting res.send(foo5.params.oops) +// bearer:expected javascript_express_cross_site_scripting res.send(params.oops) } } diff --git a/tests/javascript/express/default_cookie_config/__snapshots__/test.js.snap b/tests/javascript/express/default_cookie_config/__snapshots__/test.js.snap deleted file mode 100644 index 97ce775d9..000000000 --- a/tests/javascript/express/default_cookie_config/__snapshots__/test.js.snap +++ /dev/null @@ -1,153 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_default_cookie_config default_cookie_session_config 1`] = ` -"{ - "medium": [ - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_default_cookie_config", - "title": "Usage of cookie with default configuration", - "description": "## Description\\nTo make sure cookies don't open your application up to exploits or unauthorized access, don't use default cookie values.\\n\\n## Remediations\\n✅ Instead of the default cookie name, use generic names.\\n\\n✅ Always set a maxAge or expires value\\n\\n## Resources\\n- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_default_cookie_config", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/default_cookie_session_config.js", - "filename": ".", - "source": { - "start": 11, - "end": 16, - "column": { - "start": 17, - "end": 4 - } - }, - "sink": { - "start": 11, - "end": 16, - "column": { - "start": 17, - "end": 4 - }, - "content": "{\\n domain: \\"example.com\\",\\n httpOnly: false,\\n secure: true,\\n maxAge: 24 * 60 * 60 * 1000,\\n }" - }, - "parent_line_number": 11, - "snippet": "{\\n domain: \\"example.com\\",\\n httpOnly: false,\\n secure: true,\\n maxAge: 24 * 60 * 60 * 1000,\\n }", - "fingerprint": "71183b4d479dfbbd68cb2cfa62a497b4_0", - "old_fingerprint": "1764f09d4f779f8cdff868982d8cb613_0", - "code_extract": " cookieSession({\\n domain: \\"example.com\\",\\n httpOnly: false,\\n secure: true,\\n maxAge: 24 * 60 * 60 * 1000,\\n })" - } - ] -}" -`; - -exports[`javascript_express_default_cookie_config default_express_session_cookie_config 1`] = ` -"{ - "medium": [ - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_default_cookie_config", - "title": "Usage of cookie with default configuration", - "description": "## Description\\nTo make sure cookies don't open your application up to exploits or unauthorized access, don't use default cookie values.\\n\\n## Remediations\\n✅ Instead of the default cookie name, use generic names.\\n\\n✅ Always set a maxAge or expires value\\n\\n## Resources\\n- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_default_cookie_config", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/default_express_session_cookie_config.js", - "filename": ".", - "source": { - "start": 11, - "end": 11, - "column": { - "start": 13, - "end": 15 - } - }, - "sink": { - "start": 11, - "end": 11, - "column": { - "start": 13, - "end": 15 - }, - "content": "{}" - }, - "parent_line_number": 11, - "snippet": "{}", - "fingerprint": "71183b4d479dfbbd68cb2cfa62a497b4_0", - "old_fingerprint": "a4047d98c895b75060af4642f98e67f5_0", - "code_extract": " cookie: {}," - }, - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_default_cookie_config", - "title": "Usage of cookie with default configuration", - "description": "## Description\\nTo make sure cookies don't open your application up to exploits or unauthorized access, don't use default cookie values.\\n\\n## Remediations\\n✅ Instead of the default cookie name, use generic names.\\n\\n✅ Always set a maxAge or expires value\\n\\n## Resources\\n- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_default_cookie_config", - "line_number": 17, - "full_filename": "/tmp/bearer-scan/default_express_session_cookie_config.js", - "filename": ".", - "source": { - "start": 17, - "end": 23, - "column": { - "start": 13, - "end": 6 - } - }, - "sink": { - "start": 17, - "end": 23, - "column": { - "start": 13, - "end": 6 - }, - "content": "{\\n domain: \\"example.com\\",\\n secure: true,\\n httpOnly: false,\\n maxAge: 24 * 60 * 60 * 1000,\\n path: \\"/some-path\\",\\n }" - }, - "parent_line_number": 17, - "snippet": "{\\n domain: \\"example.com\\",\\n secure: true,\\n httpOnly: false,\\n maxAge: 24 * 60 * 60 * 1000,\\n path: \\"/some-path\\",\\n }", - "fingerprint": "71183b4d479dfbbd68cb2cfa62a497b4_1", - "old_fingerprint": "a4047d98c895b75060af4642f98e67f5_1", - "code_extract": " cookie: {\\n domain: \\"example.com\\",\\n secure: true,\\n ...omitted (buffer value 3)\\n maxAge: 24 * 60 * 60 * 1000,\\n path: \\"/some-path\\",\\n }," - }, - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_default_cookie_config", - "title": "Usage of cookie with default configuration", - "description": "## Description\\nTo make sure cookies don't open your application up to exploits or unauthorized access, don't use default cookie values.\\n\\n## Remediations\\n✅ Instead of the default cookie name, use generic names.\\n\\n✅ Always set a maxAge or expires value\\n\\n## Resources\\n- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_default_cookie_config", - "line_number": 29, - "full_filename": "/tmp/bearer-scan/default_express_session_cookie_config.js", - "filename": ".", - "source": { - "start": 29, - "end": 34, - "column": { - "start": 13, - "end": 6 - } - }, - "sink": { - "start": 29, - "end": 34, - "column": { - "start": 13, - "end": 6 - }, - "content": "{\\n domain: \\"example.com\\",\\n secure: true,\\n httpOnly: false,\\n name: \\"my-custom-cookie-name\\",\\n }" - }, - "parent_line_number": 29, - "snippet": "{\\n domain: \\"example.com\\",\\n secure: true,\\n httpOnly: false,\\n name: \\"my-custom-cookie-name\\",\\n }", - "fingerprint": "71183b4d479dfbbd68cb2cfa62a497b4_2", - "old_fingerprint": "a4047d98c895b75060af4642f98e67f5_2", - "code_extract": " cookie: {\\n domain: \\"example.com\\",\\n secure: true,\\n httpOnly: false,\\n name: \\"my-custom-cookie-name\\",\\n }," - } - ] -}" -`; - -exports[`javascript_express_default_cookie_config ok_cookie_configured 1`] = `"{}"`; diff --git a/tests/javascript/express/default_cookie_config/test.js b/tests/javascript/express/default_cookie_config/test.js index a8734d752..dd3a86e52 100644 --- a/tests/javascript/express/default_cookie_config/test.js +++ b/tests/javascript/express/default_cookie_config/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("default_cookie_session_config", () => { + const testCase = "default_cookie_session_config.js" + + const results = invoke(testCase) - test("default_cookie_session_config", () => { - const testCase = "default_cookie_session_config.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("default_express_session_cookie_config", () => { - const testCase = "default_express_session_cookie_config.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("default_express_session_cookie_config", () => { + const testCase = "default_express_session_cookie_config.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_cookie_configured", () => { - const testCase = "ok_cookie_configured.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_cookie_configured", () => { + const testCase = "ok_cookie_configured.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/default_cookie_config/testdata/default_cookie_session_config.js b/tests/javascript/express/default_cookie_config/testdata/default_cookie_session_config.js index 79e1e9f46..3a9d065c8 100644 --- a/tests/javascript/express/default_cookie_config/testdata/default_cookie_session_config.js +++ b/tests/javascript/express/default_cookie_config/testdata/default_cookie_session_config.js @@ -8,6 +8,7 @@ app.use(helmet()) app.use(helmet.hidePoweredBy()) app.use( +// bearer:expected javascript_express_default_cookie_config cookieSession({ domain: "example.com", httpOnly: false, diff --git a/tests/javascript/express/default_cookie_config/testdata/default_express_session_cookie_config.js b/tests/javascript/express/default_cookie_config/testdata/default_express_session_cookie_config.js index 8cc6002a3..3c26a4251 100644 --- a/tests/javascript/express/default_cookie_config/testdata/default_express_session_cookie_config.js +++ b/tests/javascript/express/default_cookie_config/testdata/default_express_session_cookie_config.js @@ -8,12 +8,14 @@ app.use(helmet.hidePoweredBy()) app.use( session({ +// bearer:expected javascript_express_default_cookie_config cookie: {}, }) ) app.use( session({ +// bearer:expected javascript_express_default_cookie_config cookie: { domain: "example.com", secure: true, @@ -26,6 +28,7 @@ app.use( app.use( session({ +// bearer:expected javascript_express_default_cookie_config cookie: { domain: "example.com", secure: true, diff --git a/tests/javascript/express/default_session_config/__snapshots__/test.js.snap b/tests/javascript/express/default_session_config/__snapshots__/test.js.snap deleted file mode 100644 index 2abe9e936..000000000 --- a/tests/javascript/express/default_session_config/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_default_session_config default_session_config 1`] = ` -"{ - "medium": [ - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_default_session_config", - "title": "Usage of session cookie with default configuration", - "description": "## Description\\nTo make sure session cookies don't open your application up to exploits or unauthorized access, don't use default cookie values.\\n\\n## Remediations\\n✅ Instead of the default session name, use generic names.\\n\\n## Resources\\n- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_default_session_config", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/default_session_config.js", - "filename": ".", - "source": { - "start": 9, - "end": 9, - "column": { - "start": 17, - "end": 19 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 17, - "end": 19 - }, - "content": "{}" - }, - "parent_line_number": 9, - "snippet": "{}", - "fingerprint": "037459ef0f358c29fa721b91de9aa785_0", - "old_fingerprint": "3e590f4cbe89499b620b31fb13134f6e_0", - "code_extract": "app.use(session({}))" - } - ] -}" -`; - -exports[`javascript_express_default_session_config ok_session_configured 1`] = `"{}"`; diff --git a/tests/javascript/express/default_session_config/test.js b/tests/javascript/express/default_session_config/test.js index 1d48a5efb..b18f19ca9 100644 --- a/tests/javascript/express/default_session_config/test.js +++ b/tests/javascript/express/default_session_config/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("default_session_config", () => { + const testCase = "default_session_config.js" + + const results = invoke(testCase) - test("default_session_config", () => { - const testCase = "default_session_config.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_session_configured", () => { - const testCase = "ok_session_configured.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_session_configured", () => { + const testCase = "ok_session_configured.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/default_session_config/testdata/default_session_config.js b/tests/javascript/express/default_session_config/testdata/default_session_config.js index d713a7268..c159cccf5 100644 --- a/tests/javascript/express/default_session_config/testdata/default_session_config.js +++ b/tests/javascript/express/default_session_config/testdata/default_session_config.js @@ -6,4 +6,5 @@ var app = express() app.use(helmet()) app.use(helmet.hidePoweredBy()) +// bearer:expected javascript_express_default_session_config app.use(session({})) diff --git a/tests/javascript/express/exposed_dir_listing/__snapshots__/test.js.snap b/tests/javascript/express/exposed_dir_listing/__snapshots__/test.js.snap deleted file mode 100644 index 1c7fec137..000000000 --- a/tests/javascript/express/exposed_dir_listing/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_exposed_dir_listing ok_app_use 1`] = `"{}"`; - -exports[`javascript_express_exposed_dir_listing serve_index_in_app_use 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "548" - ], - "id": "javascript_express_exposed_dir_listing", - "title": "Missing access restriction on directory listing", - "description": "## Description\\nInappropriate exposure of a directory listing could give attackers access to sensitive data or source code, either directly or through exploitation of an exposed file structure.\\n\\n## Remediations\\n✅ Restrict access to sensitive directories and files\\n\\n## Resources\\n- [Express Serve index middleware](https://expressjs.com/en/resources/middleware/serve-index.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_exposed_dir_listing", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/serve_index_in_app_use.js", - "filename": ".", - "source": { - "start": 9, - "end": 9, - "column": { - "start": 1, - "end": 52 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 1, - "end": 52 - }, - "content": "app.use(\\"/public\\", serveIndex(__dirname + \\"files\\"))" - }, - "parent_line_number": 9, - "snippet": "app.use(\\"/public\\", serveIndex(__dirname + \\"files\\"))", - "fingerprint": "e5160a3a6c8ab399600f1eef9413fa8d_0", - "old_fingerprint": "dd4210f84fbf2407460fbaf103e463d2_0", - "code_extract": "app.use(\\"/public\\", serveIndex(__dirname + \\"files\\"))" - } - ] -}" -`; diff --git a/tests/javascript/express/exposed_dir_listing/test.js b/tests/javascript/express/exposed_dir_listing/test.js index 06003255f..23e91dbb8 100644 --- a/tests/javascript/express/exposed_dir_listing/test.js +++ b/tests/javascript/express/exposed_dir_listing/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_app_use", () => { + const testCase = "ok_app_use.js" + + const results = invoke(testCase) - test("ok_app_use", () => { - const testCase = "ok_app_use.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("serve_index_in_app_use", () => { - const testCase = "serve_index_in_app_use.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("serve_index_in_app_use", () => { + const testCase = "serve_index_in_app_use.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/exposed_dir_listing/testdata/serve_index_in_app_use.js b/tests/javascript/express/exposed_dir_listing/testdata/serve_index_in_app_use.js index c0cd7dbea..1f9b4761a 100644 --- a/tests/javascript/express/exposed_dir_listing/testdata/serve_index_in_app_use.js +++ b/tests/javascript/express/exposed_dir_listing/testdata/serve_index_in_app_use.js @@ -6,6 +6,7 @@ var app = express() app.use(helmet()) app.use(helmet.hidePoweredBy()) +// bearer:expected javascript_express_exposed_dir_listing app.use("/public", serveIndex(__dirname + "files")) app.listen(3000) diff --git a/tests/javascript/express/external_file_upload/__snapshots__/test.js.snap b/tests/javascript/express/external_file_upload/__snapshots__/test.js.snap deleted file mode 100644 index 8435cba39..000000000 --- a/tests/javascript/express/external_file_upload/__snapshots__/test.js.snap +++ /dev/null @@ -1,146 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_external_file_upload ok_send_file 1`] = `"{}"`; - -exports[`javascript_express_external_file_upload send_file_with_external_input 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "73" - ], - "id": "javascript_express_external_file_upload", - "title": "Unsanitized user input in file request", - "description": "## Description\\nPassing unsanitized user input to the sendFile API is bad practice and can lead to path manipulation, by which attackers can gain access to resources and data outside of the intended scope.\\n\\n## Remediations\\n✅ Set the root option to be an absolute path to a directory\\n\\n\`\`\`javascript\\napp.post(\\"/upload\\", (req, res) => {\\n var options = {\\n root: path.join(__dirname, \\"upload\\")\\n }\\n res.sendFile(req.params.filename, options)\\n}\\n\`\`\`\\n\\n## Resources\\n- [Express sendFile API reference](http://expressjs.com/en/5x/api.html#res.sendFile)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_external_file_upload", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/send_file_with_external_input.js", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 3, - "end": 21 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 3, - "end": 21 - }, - "content": "res.sendFile(file)" - }, - "parent_line_number": 12, - "snippet": "res.sendFile(file)", - "fingerprint": "f39779a929c915fb55fa930e548d6d6f_0", - "old_fingerprint": "810bde41a13d23d020b32bc1302aa56f_0", - "code_extract": " res.sendFile(file)" - }, - { - "cwe_ids": [ - "73" - ], - "id": "javascript_express_external_file_upload", - "title": "Unsanitized user input in file request", - "description": "## Description\\nPassing unsanitized user input to the sendFile API is bad practice and can lead to path manipulation, by which attackers can gain access to resources and data outside of the intended scope.\\n\\n## Remediations\\n✅ Set the root option to be an absolute path to a directory\\n\\n\`\`\`javascript\\napp.post(\\"/upload\\", (req, res) => {\\n var options = {\\n root: path.join(__dirname, \\"upload\\")\\n }\\n res.sendFile(req.params.filename, options)\\n}\\n\`\`\`\\n\\n## Resources\\n- [Express sendFile API reference](http://expressjs.com/en/5x/api.html#res.sendFile)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_external_file_upload", - "line_number": 13, - "full_filename": "/tmp/bearer-scan/send_file_with_external_input.js", - "filename": ".", - "source": { - "start": 13, - "end": 13, - "column": { - "start": 3, - "end": 35 - } - }, - "sink": { - "start": 13, - "end": 13, - "column": { - "start": 3, - "end": 35 - }, - "content": "res.sendFile(path.resolve(file))" - }, - "parent_line_number": 13, - "snippet": "res.sendFile(path.resolve(file))", - "fingerprint": "f39779a929c915fb55fa930e548d6d6f_1", - "old_fingerprint": "810bde41a13d23d020b32bc1302aa56f_1", - "code_extract": " res.sendFile(path.resolve(file))" - }, - { - "cwe_ids": [ - "73" - ], - "id": "javascript_express_external_file_upload", - "title": "Unsanitized user input in file request", - "description": "## Description\\nPassing unsanitized user input to the sendFile API is bad practice and can lead to path manipulation, by which attackers can gain access to resources and data outside of the intended scope.\\n\\n## Remediations\\n✅ Set the root option to be an absolute path to a directory\\n\\n\`\`\`javascript\\napp.post(\\"/upload\\", (req, res) => {\\n var options = {\\n root: path.join(__dirname, \\"upload\\")\\n }\\n res.sendFile(req.params.filename, options)\\n}\\n\`\`\`\\n\\n## Resources\\n- [Express sendFile API reference](http://expressjs.com/en/5x/api.html#res.sendFile)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_external_file_upload", - "line_number": 14, - "full_filename": "/tmp/bearer-scan/send_file_with_external_input.js", - "filename": ".", - "source": { - "start": 14, - "end": 14, - "column": { - "start": 3, - "end": 46 - } - }, - "sink": { - "start": 14, - "end": 14, - "column": { - "start": 3, - "end": 46 - }, - "content": "res.sendFile(req.params.file, {}, () => {})" - }, - "parent_line_number": 14, - "snippet": "res.sendFile(req.params.file, {}, () => {})", - "fingerprint": "f39779a929c915fb55fa930e548d6d6f_2", - "old_fingerprint": "810bde41a13d23d020b32bc1302aa56f_2", - "code_extract": " res.sendFile(req.params.file, {}, () => {})" - }, - { - "cwe_ids": [ - "73" - ], - "id": "javascript_express_external_file_upload", - "title": "Unsanitized user input in file request", - "description": "## Description\\nPassing unsanitized user input to the sendFile API is bad practice and can lead to path manipulation, by which attackers can gain access to resources and data outside of the intended scope.\\n\\n## Remediations\\n✅ Set the root option to be an absolute path to a directory\\n\\n\`\`\`javascript\\napp.post(\\"/upload\\", (req, res) => {\\n var options = {\\n root: path.join(__dirname, \\"upload\\")\\n }\\n res.sendFile(req.params.filename, options)\\n}\\n\`\`\`\\n\\n## Resources\\n- [Express sendFile API reference](http://expressjs.com/en/5x/api.html#res.sendFile)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_external_file_upload", - "line_number": 15, - "full_filename": "/tmp/bearer-scan/send_file_with_external_input.js", - "filename": ".", - "source": { - "start": 15, - "end": 15, - "column": { - "start": 3, - "end": 76 - } - }, - "sink": { - "start": 15, - "end": 15, - "column": { - "start": 3, - "end": 76 - }, - "content": "res.sendFile(\\"file.txt\\", { root: path.join(__dirname, req.params.root) })" - }, - "parent_line_number": 15, - "snippet": "res.sendFile(\\"file.txt\\", { root: path.join(__dirname, req.params.root) })", - "fingerprint": "f39779a929c915fb55fa930e548d6d6f_3", - "old_fingerprint": "810bde41a13d23d020b32bc1302aa56f_3", - "code_extract": " res.sendFile(\\"file.txt\\", { root: path.join(__dirname, req.params.root) })" - } - ] -}" -`; diff --git a/tests/javascript/express/external_file_upload/test.js b/tests/javascript/express/external_file_upload/test.js index a1127403e..9323911bc 100644 --- a/tests/javascript/express/external_file_upload/test.js +++ b/tests/javascript/express/external_file_upload/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_send_file", () => { + const testCase = "ok_send_file.js" + + const results = invoke(testCase) - test("ok_send_file", () => { - const testCase = "ok_send_file.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("send_file_with_external_input", () => { - const testCase = "send_file_with_external_input.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("send_file_with_external_input", () => { + const testCase = "send_file_with_external_input.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/external_file_upload/testdata/send_file_with_external_input.js b/tests/javascript/express/external_file_upload/testdata/send_file_with_external_input.js index ff3796492..ef585652c 100644 --- a/tests/javascript/express/external_file_upload/testdata/send_file_with_external_input.js +++ b/tests/javascript/express/external_file_upload/testdata/send_file_with_external_input.js @@ -9,8 +9,12 @@ var path = require("path") app.get("/", function (req, res) { var file = req.params.file +// bearer:expected javascript_express_external_file_upload res.sendFile(file) +// bearer:expected javascript_express_external_file_upload res.sendFile(path.resolve(file)) +// bearer:expected javascript_express_external_file_upload res.sendFile(req.params.file, {}, () => {}) +// bearer:expected javascript_express_external_file_upload res.sendFile("file.txt", { root: path.join(__dirname, req.params.root) }) }) diff --git a/tests/javascript/express/external_resource/__snapshots__/test.js.snap b/tests/javascript/express/external_resource/__snapshots__/test.js.snap deleted file mode 100644 index f6b7fcab0..000000000 --- a/tests/javascript/express/external_resource/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_external_resource ok_known_resource 1`] = `"{}"`; - -exports[`javascript_express_external_resource render_external_resource 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "706" - ], - "id": "javascript_express_external_resource", - "title": "Unsanitized user input in resource rendering", - "description": "## Description\\nUsing raw unsanitized input when rendering resources is bad practice.\\n\\n## Remediations\\n❌ Avoid passing user or request input to res.render().\\n\\n✅ Sanitize the input or use a safelist\\n\\nWhere it is unavoidable to rely on user input, sanitize the input or use a safelist to keep the rendered resources within the expected scope.\\n\\n\`\`\`javascript\\nvar path = req.body.path\\nif (['users', 'posts', 'pages'].includes(path)) {\\n return res.render(\`\${path}/success\`)\\n}\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_external_resource", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/render_external_resource.js", - "filename": ".", - "source": { - "start": 9, - "end": 9, - "column": { - "start": 10, - "end": 62 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 10, - "end": 62 - }, - "content": "res.render(req.query.path + \\"/results\\", { page: 1 })" - }, - "parent_line_number": 9, - "snippet": "res.render(req.query.path + \\"/results\\", { page: 1 })", - "fingerprint": "b370881b6e854d7e31487a8465e91ae0_0", - "old_fingerprint": "d8919012013f508be4d0a0076cba19f1_0", - "code_extract": " return res.render(req.query.path + \\"/results\\", { page: 1 })" - } - ] -}" -`; diff --git a/tests/javascript/express/external_resource/test.js b/tests/javascript/express/external_resource/test.js index a783ef5f1..973b78adf 100644 --- a/tests/javascript/express/external_resource/test.js +++ b/tests/javascript/express/external_resource/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_known_resource", () => { + const testCase = "ok_known_resource.js" + + const results = invoke(testCase) - test("ok_known_resource", () => { - const testCase = "ok_known_resource.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("render_external_resource", () => { - const testCase = "render_external_resource.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("render_external_resource", () => { + const testCase = "render_external_resource.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/external_resource/testdata/render_external_resource.js b/tests/javascript/express/external_resource/testdata/render_external_resource.js index 16110bfd1..6b6480ad8 100644 --- a/tests/javascript/express/external_resource/testdata/render_external_resource.js +++ b/tests/javascript/express/external_resource/testdata/render_external_resource.js @@ -6,5 +6,6 @@ app.use(helmet()) app.use(helmet.hidePoweredBy()) app.get("/bad", (req, res) => { +// bearer:expected javascript_express_external_resource return res.render(req.query.path + "/results", { page: 1 }) }) diff --git a/tests/javascript/express/hardcoded_secret/__snapshots__/test.js.snap b/tests/javascript/express/hardcoded_secret/__snapshots__/test.js.snap deleted file mode 100644 index 7076459aa..000000000 --- a/tests/javascript/express/hardcoded_secret/__snapshots__/test.js.snap +++ /dev/null @@ -1,289 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_hardcoded_secret hardcoded_secret_in_jwt 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "798" - ], - "id": "javascript_express_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: \\"shh-my-secret\\",\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: process.env.secret,\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_hardcoded_secret", - "line_number": 14, - "full_filename": "/tmp/bearer-scan/hardcoded_secret_in_jwt.js", - "filename": ".", - "source": { - "start": 14, - "end": 14, - "column": { - "start": 3, - "end": 48 - } - }, - "sink": { - "start": 14, - "end": 14, - "column": { - "start": 3, - "end": 48 - }, - "content": "expressjwt({ secret: \\"my-hardcoded-secret\\" })" - }, - "parent_line_number": 14, - "snippet": "expressjwt({ secret: \\"my-hardcoded-secret\\" })", - "fingerprint": "1cfb7760604e7cc75fe776199e231fb6_0", - "old_fingerprint": "2c914a536f4a4f72a15ad382685fd5ef_0", - "code_extract": " expressjwt({ secret: \\"my-hardcoded-secret\\" })," - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_express_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: \\"shh-my-secret\\",\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: process.env.secret,\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_hardcoded_secret", - "line_number": 22, - "full_filename": "/tmp/bearer-scan/hardcoded_secret_in_jwt.js", - "filename": ".", - "source": { - "start": 22, - "end": 22, - "column": { - "start": 1, - "end": 31 - } - }, - "sink": { - "start": 22, - "end": 22, - "column": { - "start": 1, - "end": 31 - }, - "content": "jwt.sign({ x: 42 }, secret, y)" - }, - "parent_line_number": 22, - "snippet": "jwt.sign({ x: 42 }, secret, y)", - "fingerprint": "1cfb7760604e7cc75fe776199e231fb6_1", - "old_fingerprint": "2c914a536f4a4f72a15ad382685fd5ef_1", - "code_extract": "jwt.sign({ x: 42 }, secret, y)" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_express_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: \\"shh-my-secret\\",\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: process.env.secret,\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_hardcoded_secret", - "line_number": 24, - "full_filename": "/tmp/bearer-scan/hardcoded_secret_in_jwt.js", - "filename": ".", - "source": { - "start": 24, - "end": 24, - "column": { - "start": 19, - "end": 43 - } - }, - "sink": { - "start": 24, - "end": 24, - "column": { - "start": 19, - "end": 43 - }, - "content": "jwt2({ secret: secret })" - }, - "parent_line_number": 24, - "snippet": "jwt2({ secret: secret })", - "fingerprint": "1cfb7760604e7cc75fe776199e231fb6_2", - "old_fingerprint": "2c914a536f4a4f72a15ad382685fd5ef_2", - "code_extract": "app.get(\\"/bad-2\\", jwt2({ secret: secret }), function (_req, res) {" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_express_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: \\"shh-my-secret\\",\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: process.env.secret,\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_hardcoded_secret", - "line_number": 29, - "full_filename": "/tmp/bearer-scan/hardcoded_secret_in_jwt.js", - "filename": ".", - "source": { - "start": 29, - "end": 29, - "column": { - "start": 1, - "end": 23 - } - }, - "sink": { - "start": 29, - "end": 29, - "column": { - "start": 1, - "end": 23 - }, - "content": "foo({ x: 42 }, secret)" - }, - "parent_line_number": 29, - "snippet": "foo({ x: 42 }, secret)", - "fingerprint": "1cfb7760604e7cc75fe776199e231fb6_3", - "old_fingerprint": "2c914a536f4a4f72a15ad382685fd5ef_3", - "code_extract": "foo({ x: 42 }, secret)" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_express_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: \\"shh-my-secret\\",\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: process.env.secret,\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_hardcoded_secret", - "line_number": 32, - "full_filename": "/tmp/bearer-scan/hardcoded_secret_in_jwt.js", - "filename": ".", - "source": { - "start": 32, - "end": 32, - "column": { - "start": 1, - "end": 24 - } - }, - "sink": { - "start": 32, - "end": 32, - "column": { - "start": 1, - "end": 24 - }, - "content": "sign({ x: 42 }, secret)" - }, - "parent_line_number": 32, - "snippet": "sign({ x: 42 }, secret)", - "fingerprint": "1cfb7760604e7cc75fe776199e231fb6_4", - "old_fingerprint": "2c914a536f4a4f72a15ad382685fd5ef_4", - "code_extract": "sign({ x: 42 }, secret)" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_express_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: \\"shh-my-secret\\",\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: process.env.secret,\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_hardcoded_secret", - "line_number": 37, - "full_filename": "/tmp/bearer-scan/hardcoded_secret_in_jwt.js", - "filename": ".", - "source": { - "start": 37, - "end": 37, - "column": { - "start": 3, - "end": 49 - } - }, - "sink": { - "start": 37, - "end": 37, - "column": { - "start": 3, - "end": 49 - }, - "content": "expressjwt2({ secret: \\"my-hardcoded-secret\\" })" - }, - "parent_line_number": 37, - "snippet": "expressjwt2({ secret: \\"my-hardcoded-secret\\" })", - "fingerprint": "1cfb7760604e7cc75fe776199e231fb6_5", - "old_fingerprint": "2c914a536f4a4f72a15ad382685fd5ef_5", - "code_extract": " expressjwt2({ secret: \\"my-hardcoded-secret\\" })," - } - ] -}" -`; - -exports[`javascript_express_hardcoded_secret hardcoded_secret_in_session 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "798" - ], - "id": "javascript_express_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: \\"shh-my-secret\\",\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: process.env.secret,\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_hardcoded_secret", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/hardcoded_secret_in_session.js", - "filename": ".", - "source": { - "start": 12, - "end": 15, - "column": { - "start": 3, - "end": 5 - } - }, - "sink": { - "start": 12, - "end": 15, - "column": { - "start": 3, - "end": 5 - }, - "content": "session({\\n name: \\"my-custom-session-name\\",\\n secret: \\"my-hardcoded-secret\\",\\n })" - }, - "parent_line_number": 12, - "snippet": "session({\\n name: \\"my-custom-session-name\\",\\n secret: \\"my-hardcoded-secret\\",\\n })", - "fingerprint": "1cfb7760604e7cc75fe776199e231fb6_0", - "old_fingerprint": "d7b3e3dde37854840dd24e2179af6ca9_0", - "code_extract": " session({\\n name: \\"my-custom-session-name\\",\\n secret: \\"my-hardcoded-secret\\",\\n })" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_express_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: \\"shh-my-secret\\",\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n app.use(\\n session({\\n secret: process.env.secret,\\n name: \\"my-custom-session-name\\",\\n })\\n)\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_hardcoded_secret", - "line_number": 23, - "full_filename": "/tmp/bearer-scan/hardcoded_secret_in_session.js", - "filename": ".", - "source": { - "start": 23, - "end": 23, - "column": { - "start": 9, - "end": 31 - } - }, - "sink": { - "start": 23, - "end": 23, - "column": { - "start": 9, - "end": 31 - }, - "content": "session(sessionConfig)" - }, - "parent_line_number": 23, - "snippet": "session(sessionConfig)", - "fingerprint": "1cfb7760604e7cc75fe776199e231fb6_1", - "old_fingerprint": "d7b3e3dde37854840dd24e2179af6ca9_1", - "code_extract": "app.use(session(sessionConfig))" - } - ] -}" -`; - -exports[`javascript_express_hardcoded_secret ok_no_hardcoded_secrets 1`] = `"{}"`; diff --git a/tests/javascript/express/hardcoded_secret/test.js b/tests/javascript/express/hardcoded_secret/test.js index 2fa3604d7..69127f361 100644 --- a/tests/javascript/express/hardcoded_secret/test.js +++ b/tests/javascript/express/hardcoded_secret/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("hardcoded_secret_in_jwt", () => { + const testCase = "hardcoded_secret_in_jwt.js" + + const results = invoke(testCase) - test("hardcoded_secret_in_jwt", () => { - const testCase = "hardcoded_secret_in_jwt.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("hardcoded_secret_in_session", () => { - const testCase = "hardcoded_secret_in_session.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("hardcoded_secret_in_session", () => { + const testCase = "hardcoded_secret_in_session.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_no_hardcoded_secrets", () => { - const testCase = "ok_no_hardcoded_secrets.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_no_hardcoded_secrets", () => { + const testCase = "ok_no_hardcoded_secrets.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/hardcoded_secret/testdata/hardcoded_secret_in_jwt.js b/tests/javascript/express/hardcoded_secret/testdata/hardcoded_secret_in_jwt.js index a04b79e55..7575abf98 100644 --- a/tests/javascript/express/hardcoded_secret/testdata/hardcoded_secret_in_jwt.js +++ b/tests/javascript/express/hardcoded_secret/testdata/hardcoded_secret_in_jwt.js @@ -11,6 +11,7 @@ app = express.app() app.get( "/bad", +// bearer:expected javascript_express_hardcoded_secret expressjwt({ secret: "my-hardcoded-secret" }), function (_req, res) { res.sendStatus(200) @@ -19,21 +20,26 @@ app.get( var secret = "my-hardcoded-secret" +// bearer:expected javascript_express_hardcoded_secret jwt.sign({ x: 42 }, secret, y) +// bearer:expected javascript_express_hardcoded_secret app.get("/bad-2", jwt2({ secret: secret }), function (_req, res) { res.sendStatus(200) }) import { sign as foo, y as bar } from 'jsonwebtoken' +// bearer:expected javascript_express_hardcoded_secret foo({ x: 42 }, secret) const { sign, y } = require("jsonwebtoken") +// bearer:expected javascript_express_hardcoded_secret sign({ x: 42 }, secret) import * as expressjwt2 from "expressjwt" app.get( "/bad", +// bearer:expected javascript_express_hardcoded_secret expressjwt2({ secret: "my-hardcoded-secret" }), function (_req, res) { res.sendStatus(200) diff --git a/tests/javascript/express/hardcoded_secret/testdata/hardcoded_secret_in_session.js b/tests/javascript/express/hardcoded_secret/testdata/hardcoded_secret_in_session.js index 9c1a241f2..303ff63e9 100644 --- a/tests/javascript/express/hardcoded_secret/testdata/hardcoded_secret_in_session.js +++ b/tests/javascript/express/hardcoded_secret/testdata/hardcoded_secret_in_session.js @@ -9,6 +9,7 @@ app.use(helmet.hidePoweredBy()) app = express.app() app.use( +// bearer:expected javascript_express_hardcoded_secret session({ name: "my-custom-session-name", secret: "my-hardcoded-secret", @@ -20,6 +21,7 @@ var sessionConfig = { secret: "hardcoded-secret", } +// bearer:expected javascript_express_hardcoded_secret app.use(session(sessionConfig)) var sessionConfig = { diff --git a/tests/javascript/express/helmet_missing/__snapshots__/test.js.snap b/tests/javascript/express/helmet_missing/__snapshots__/test.js.snap deleted file mode 100644 index 2406f5938..000000000 --- a/tests/javascript/express/helmet_missing/__snapshots__/test.js.snap +++ /dev/null @@ -1,48 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_helmet_missing index 1`] = `"{}"`; - -exports[`javascript_express_helmet_missing insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_helmet_missing", - "title": "Missing Helmet configuration on HTTP headers", - "description": "## Description\\n\\nHelmet can help protect your app from some well-known web vulnerabilities by setting HTTP headers appropriately.\\n\\n## Remediations\\n\\n✅ Use Helmet middleware\\n\\n\`\`\`javascript\\nconst helmet = require(\\"helmet\\")\\napp.use(helmet())\\n\`\`\`\\n\\n## Resources\\n\\n- [Express Security Best Practices: Use Helmet](https://expressjs.com/en/advanced/best-practice-security.html#use-helmet)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_helmet_missing", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 11, - "end": 15 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 11, - "end": 15 - }, - "content": "ex()" - }, - "parent_line_number": 4, - "snippet": "ex()", - "fingerprint": "124650418e34cb20fdd3bfe81d2a05e2_0", - "old_fingerprint": "623670335300b582638d97b40e11dc87_0", - "code_extract": "const a = ex()" - } - ] -}" -`; - -exports[`javascript_express_helmet_missing secure 1`] = `"{}"`; - -exports[`javascript_express_helmet_missing secure_part 1`] = `"{}"`; diff --git a/tests/javascript/express/helmet_missing/test.js b/tests/javascript/express/helmet_missing/test.js index 3ccc68c13..33df2ba8b 100644 --- a/tests/javascript/express/helmet_missing/test.js +++ b/tests/javascript/express/helmet_missing/test.js @@ -1,31 +1,50 @@ -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("index", () => { + const testCase = "index.ts" + + const results = invoke(testCase) - test("index", () => { - const testCase = "index.ts" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure_part", () => { - const testCase = "secure_part.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure_part", () => { + const testCase = "secure_part.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/helmet_missing/testdata/insecure.js b/tests/javascript/express/helmet_missing/testdata/insecure.js index f7806f7ca..04b117fe6 100644 --- a/tests/javascript/express/helmet_missing/testdata/insecure.js +++ b/tests/javascript/express/helmet_missing/testdata/insecure.js @@ -1,6 +1,7 @@ const ex = require("express") const cors = require("cors") +// bearer:expected javascript_express_helmet_missing const a = ex() a.use(express.json()) a.use(cors()) diff --git a/tests/javascript/express/https_protocol_missing/__snapshots__/test.js.snap b/tests/javascript/express/https_protocol_missing/__snapshots__/test.js.snap deleted file mode 100644 index 154c93696..000000000 --- a/tests/javascript/express/https_protocol_missing/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_https_protocol_missing insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "319" - ], - "id": "javascript_express_https_protocol_missing", - "title": "Missing secure HTTP server configuration", - "description": "## Description\\nUse HTTPS wherever possible. HTTPS uses the TLS (Transport Layer Security) protocol to encrypt communication, making it more secure than HTTP.\\n\\n## Remediations\\n✅ Use the \`https\` module when calling \`createServer()\`\\n\\n\`\`\`javascript\\nvar https = require('https');\\nvar express = require('express');\\nvar app = express();\\n\\nvar httpsServer = https.createServer(app)\\nhttpsServer.listen(8080);\\n\`\`\`\\n\\n## Resources\\n- [Express Security Best Practices: use TLS](https://expressjs.com/en/advanced/best-practice-security.html#use-tls)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_https_protocol_missing", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 23 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 23 - }, - "content": "http.createServer(app)" - }, - "parent_line_number": 1, - "snippet": "http.createServer(app)", - "fingerprint": "d3c9698c21c130aa1d04a0c9d85abe8f_0", - "old_fingerprint": "cc0f122ba5d59ef3fe0edbf90db249bf_0", - "code_extract": "http.createServer(app).listen(port, () => {" - } - ] -}" -`; - -exports[`javascript_express_https_protocol_missing secure 1`] = `"{}"`; diff --git a/tests/javascript/express/https_protocol_missing/test.js b/tests/javascript/express/https_protocol_missing/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/express/https_protocol_missing/test.js +++ b/tests/javascript/express/https_protocol_missing/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/https_protocol_missing/testdata/insecure.js b/tests/javascript/express/https_protocol_missing/testdata/insecure.js index 52ff99f3c..39a6ef593 100644 --- a/tests/javascript/express/https_protocol_missing/testdata/insecure.js +++ b/tests/javascript/express/https_protocol_missing/testdata/insecure.js @@ -1,3 +1,4 @@ +// bearer:expected javascript_express_https_protocol_missing http.createServer(app).listen(port, () => { console.log("hello world"); }); \ No newline at end of file diff --git a/tests/javascript/express/insecure_allow_origin/__snapshots__/test.js.snap b/tests/javascript/express/insecure_allow_origin/__snapshots__/test.js.snap deleted file mode 100644 index 4ef2a03e9..000000000 --- a/tests/javascript/express/insecure_allow_origin/__snapshots__/test.js.snap +++ /dev/null @@ -1,119 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_insecure_allow_origin insecure_allow_origin 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "346" - ], - "id": "javascript_express_insecure_allow_origin", - "title": "Unsanitized user input in Access-Control-Allow-Origin", - "description": "## Description\\nDo not use unverified user-defined input to define Access-Control-Allow-Origin. This can lead to unintended user access to sensitive data.\\n\\n## Remediations\\n❌ Avoid defining origins with user input wherever possible.\\n\\n✅ If unavoidable, be sure to verify the input or to use a safe-list.\\n\\n## Resources\\n- [OWASP Origin & Access-Control-Allow-Origin](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_insecure_allow_origin", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/insecure_allow_origin.js", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 75 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 75 - }, - "content": "res.writeHead(200, { \\"Access-Control-Allow-Origin\\": req.params.origin })" - }, - "parent_line_number": 10, - "snippet": "res.writeHead(200, { \\"Access-Control-Allow-Origin\\": req.params.origin })", - "fingerprint": "2c55192ac05fbc2a0358431b12920a25_0", - "old_fingerprint": "6c5f0d5a0935eb4b82635d3c430a1533_0", - "code_extract": " res.writeHead(200, { \\"Access-Control-Allow-Origin\\": req.params.origin })" - }, - { - "cwe_ids": [ - "346" - ], - "id": "javascript_express_insecure_allow_origin", - "title": "Unsanitized user input in Access-Control-Allow-Origin", - "description": "## Description\\nDo not use unverified user-defined input to define Access-Control-Allow-Origin. This can lead to unintended user access to sensitive data.\\n\\n## Remediations\\n❌ Avoid defining origins with user input wherever possible.\\n\\n✅ If unavoidable, be sure to verify the input or to use a safe-list.\\n\\n## Resources\\n- [OWASP Origin & Access-Control-Allow-Origin](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_insecure_allow_origin", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/insecure_allow_origin.js", - "filename": ".", - "source": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 49 - } - }, - "sink": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 49 - }, - "content": "res.set(\\"access-control-allow-origin\\", origin)" - }, - "parent_line_number": 11, - "snippet": "res.set(\\"access-control-allow-origin\\", origin)", - "fingerprint": "2c55192ac05fbc2a0358431b12920a25_1", - "old_fingerprint": "6c5f0d5a0935eb4b82635d3c430a1533_1", - "code_extract": " res.set(\\"access-control-allow-origin\\", origin)" - } - ] -}" -`; - -exports[`javascript_express_insecure_allow_origin insecure_allow_origin_query 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "346" - ], - "id": "javascript_express_insecure_allow_origin", - "title": "Unsanitized user input in Access-Control-Allow-Origin", - "description": "## Description\\nDo not use unverified user-defined input to define Access-Control-Allow-Origin. This can lead to unintended user access to sensitive data.\\n\\n## Remediations\\n❌ Avoid defining origins with user input wherever possible.\\n\\n✅ If unavoidable, be sure to verify the input or to use a safe-list.\\n\\n## Resources\\n- [OWASP Origin & Access-Control-Allow-Origin](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_insecure_allow_origin", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/insecure_allow_origin_query.js", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 55 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 55 - }, - "content": "res.setHeader(\\"Access-Control-Allow-Origin\\", origin)" - }, - "parent_line_number": 10, - "snippet": "res.setHeader(\\"Access-Control-Allow-Origin\\", origin)", - "fingerprint": "2c55192ac05fbc2a0358431b12920a25_0", - "old_fingerprint": "7e2b3f2aefd2cefd077620f64b827953_0", - "code_extract": " res.setHeader(\\"Access-Control-Allow-Origin\\", origin)" - } - ] -}" -`; - -exports[`javascript_express_insecure_allow_origin secure 1`] = `"{}"`; diff --git a/tests/javascript/express/insecure_allow_origin/test.js b/tests/javascript/express/insecure_allow_origin/test.js index 54b9948b4..72c9ed6e2 100644 --- a/tests/javascript/express/insecure_allow_origin/test.js +++ b/tests/javascript/express/insecure_allow_origin/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("insecure_allow_origin", () => { + const testCase = "insecure_allow_origin.js" + + const results = invoke(testCase) - test("insecure_allow_origin", () => { - const testCase = "insecure_allow_origin.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("insecure_allow_origin_query", () => { - const testCase = "insecure_allow_origin_query.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure_allow_origin_query", () => { + const testCase = "insecure_allow_origin_query.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/insecure_allow_origin/testdata/insecure_allow_origin.js b/tests/javascript/express/insecure_allow_origin/testdata/insecure_allow_origin.js index 2dba7d988..a6c32e634 100644 --- a/tests/javascript/express/insecure_allow_origin/testdata/insecure_allow_origin.js +++ b/tests/javascript/express/insecure_allow_origin/testdata/insecure_allow_origin.js @@ -7,6 +7,8 @@ app.use(helmet.hidePoweredBy()) app.get("/insecure", (req, res) => { var origin = req.params.origin +// bearer:expected javascript_express_insecure_allow_origin res.writeHead(200, { "Access-Control-Allow-Origin": req.params.origin }) +// bearer:expected javascript_express_insecure_allow_origin res.set("access-control-allow-origin", origin) }) diff --git a/tests/javascript/express/insecure_allow_origin/testdata/insecure_allow_origin_query.js b/tests/javascript/express/insecure_allow_origin/testdata/insecure_allow_origin_query.js index 1a6ced646..3d2a3ffb7 100644 --- a/tests/javascript/express/insecure_allow_origin/testdata/insecure_allow_origin_query.js +++ b/tests/javascript/express/insecure_allow_origin/testdata/insecure_allow_origin_query.js @@ -7,5 +7,6 @@ app.use(helmet.hidePoweredBy()) app.get("/insecure", (req, res) => { var origin = req.query.origin +// bearer:expected javascript_express_insecure_allow_origin res.setHeader("Access-Control-Allow-Origin", origin) }) diff --git a/tests/javascript/express/insecure_cookie/__snapshots__/test.js.snap b/tests/javascript/express/insecure_cookie/__snapshots__/test.js.snap deleted file mode 100644 index 912b7bc40..000000000 --- a/tests/javascript/express/insecure_cookie/__snapshots__/test.js.snap +++ /dev/null @@ -1,126 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_insecure_cookie insecure_cookie 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "614" - ], - "id": "javascript_express_insecure_cookie", - "title": "Missing secure options for cookie detected", - "description": "## Description\\n\\nA cookie that is configured to be secure ensures that a client will only send the cookie to the server when HTTPS is being used.\\nThis prevents the cookie from being observed by unauthorized third parties.\\n\\n## Remediations\\n\\n✅ Set \`secure\` values to \`true\` to force cookies to only send over HTTPS.\\n \`\`\`javascript\\n cookie({{ secure: true }})\\n \`\`\`\\n\\n## Resources\\n- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_insecure_cookie", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/insecure_cookie.js", - "filename": ".", - "source": { - "start": 10, - "end": 19, - "column": { - "start": 11, - "end": 4 - } - }, - "sink": { - "start": 10, - "end": 19, - "column": { - "start": 11, - "end": 4 - }, - "content": "{\\n cookie: {\\n domain: \\"example.com\\",\\n secure: false, // Ensures the browser only sends the cookie over HTTPS.\\n httpOnly: false,\\n name: \\"my-custom-cookie-name\\",\\n maxAge: 24 * 60 * 60 * 1000,\\n path: \\"/some-path\\",\\n },\\n }" - }, - "parent_line_number": 10, - "snippet": "{\\n cookie: {\\n domain: \\"example.com\\",\\n secure: false, // Ensures the browser only sends the cookie over HTTPS.\\n httpOnly: false,\\n name: \\"my-custom-cookie-name\\",\\n maxAge: 24 * 60 * 60 * 1000,\\n path: \\"/some-path\\",\\n },\\n }", - "fingerprint": "0b87579d3cc308770141504e6ed4a2a5_0", - "old_fingerprint": "fa507af055fc4d80a9c9e2c7f45439cc_0", - "code_extract": " session({\\n cookie: {\\n domain: \\"example.com\\",\\n ...omitted (buffer value 3)\\n path: \\"/some-path\\",\\n },\\n })" - } - ] -}" -`; - -exports[`javascript_express_insecure_cookie insecure_cookie_csurf 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "614" - ], - "id": "javascript_express_insecure_cookie", - "title": "Missing secure options for cookie detected", - "description": "## Description\\n\\nA cookie that is configured to be secure ensures that a client will only send the cookie to the server when HTTPS is being used.\\nThis prevents the cookie from being observed by unauthorized third parties.\\n\\n## Remediations\\n\\n✅ Set \`secure\` values to \`true\` to force cookies to only send over HTTPS.\\n \`\`\`javascript\\n cookie({{ secure: true }})\\n \`\`\`\\n\\n## Resources\\n- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_insecure_cookie", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/insecure_cookie_csurf.js", - "filename": ".", - "source": { - "start": 10, - "end": 13, - "column": { - "start": 28, - "end": 4 - } - }, - "sink": { - "start": 10, - "end": 13, - "column": { - "start": 28, - "end": 4 - }, - "content": "{\\n cookie: { ...csrfOptions, httpOnly: true },\\n // cookie: { secure: false, httpOnly: true },\\n }" - }, - "parent_line_number": 10, - "snippet": "{\\n cookie: { ...csrfOptions, httpOnly: true },\\n // cookie: { secure: false, httpOnly: true },\\n }", - "fingerprint": "0b87579d3cc308770141504e6ed4a2a5_0", - "old_fingerprint": "d0e5b9b4d419c509afe5c674e7c35392_0", - "code_extract": " const protection = csurf({\\n cookie: { ...csrfOptions, httpOnly: true },\\n // cookie: { secure: false, httpOnly: true },\\n })" - } - ] -}" -`; - -exports[`javascript_express_insecure_cookie insecure_cookie_session 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "614" - ], - "id": "javascript_express_insecure_cookie", - "title": "Missing secure options for cookie detected", - "description": "## Description\\n\\nA cookie that is configured to be secure ensures that a client will only send the cookie to the server when HTTPS is being used.\\nThis prevents the cookie from being observed by unauthorized third parties.\\n\\n## Remediations\\n\\n✅ Set \`secure\` values to \`true\` to force cookies to only send over HTTPS.\\n \`\`\`javascript\\n cookie({{ secure: true }})\\n \`\`\`\\n\\n## Resources\\n- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_insecure_cookie", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/insecure_cookie_session.js", - "filename": ".", - "source": { - "start": 11, - "end": 18, - "column": { - "start": 3, - "end": 5 - } - }, - "sink": { - "start": 11, - "end": 18, - "column": { - "start": 3, - "end": 5 - }, - "content": "cookieSession({\\n domain: \\"example.com\\",\\n httpOnly: false,\\n secure: false,\\n name: \\"my-custom-cookie-name\\",\\n maxAge: 24 * 60 * 60 * 1000,\\n path: \\"/some-path\\",\\n })" - }, - "parent_line_number": 11, - "snippet": "cookieSession({\\n domain: \\"example.com\\",\\n httpOnly: false,\\n secure: false,\\n name: \\"my-custom-cookie-name\\",\\n maxAge: 24 * 60 * 60 * 1000,\\n path: \\"/some-path\\",\\n })", - "fingerprint": "0b87579d3cc308770141504e6ed4a2a5_0", - "old_fingerprint": "993b8ff881a2d9574b307ebb48943593_0", - "code_extract": " cookieSession({\\n domain: \\"example.com\\",\\n httpOnly: false,\\n ...omitted (buffer value 3)\\n maxAge: 24 * 60 * 60 * 1000,\\n path: \\"/some-path\\",\\n })" - } - ] -}" -`; - -exports[`javascript_express_insecure_cookie secure_cookie_csurf 1`] = `"{}"`; diff --git a/tests/javascript/express/insecure_cookie/test.js b/tests/javascript/express/insecure_cookie/test.js index 476445751..b52523f32 100644 --- a/tests/javascript/express/insecure_cookie/test.js +++ b/tests/javascript/express/insecure_cookie/test.js @@ -1,30 +1,50 @@ -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("insecure_cookie", () => { - const testCase = "insecure_cookie.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + + test("insecure_cookie", () => { + const testCase = "insecure_cookie.js" + const results = invoke(testCase) - test("insecure_cookie_csurf", () => { - const testCase = "insecure_cookie_csurf.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + test("insecure_cookie_csurf", () => { + const testCase = "insecure_cookie_csurf.js" - test("insecure_cookie_session", () => { - const testCase = "insecure_cookie_session.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + const results = invoke(testCase) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - test("secure_cookie_csurf", () => { - const testCase = "secure_cookie_csurf.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure_cookie_session", () => { + const testCase = "insecure_cookie_session.js" + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("secure_cookie_csurf", () => { + const testCase = "secure_cookie_csurf.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + }) \ No newline at end of file diff --git a/tests/javascript/express/insecure_cookie/testdata/insecure_cookie.js b/tests/javascript/express/insecure_cookie/testdata/insecure_cookie.js index a759910cf..2f7d90860 100644 --- a/tests/javascript/express/insecure_cookie/testdata/insecure_cookie.js +++ b/tests/javascript/express/insecure_cookie/testdata/insecure_cookie.js @@ -7,6 +7,7 @@ app.use(helmet()) app.use(helmet.hidePoweredBy()) app.use( +// bearer:expected javascript_express_insecure_cookie session({ cookie: { domain: "example.com", diff --git a/tests/javascript/express/insecure_cookie/testdata/insecure_cookie_csurf.js b/tests/javascript/express/insecure_cookie/testdata/insecure_cookie_csurf.js index 0ee5e52ef..f4f9eabdb 100644 --- a/tests/javascript/express/insecure_cookie/testdata/insecure_cookie_csurf.js +++ b/tests/javascript/express/insecure_cookie/testdata/insecure_cookie_csurf.js @@ -7,6 +7,7 @@ export const csrfOptions = { } export default function getCsurf() { +// bearer:expected javascript_express_insecure_cookie const protection = csurf({ cookie: { ...csrfOptions, httpOnly: true }, // cookie: { secure: false, httpOnly: true }, diff --git a/tests/javascript/express/insecure_cookie/testdata/insecure_cookie_session.js b/tests/javascript/express/insecure_cookie/testdata/insecure_cookie_session.js index 38a97085d..ea50873e3 100644 --- a/tests/javascript/express/insecure_cookie/testdata/insecure_cookie_session.js +++ b/tests/javascript/express/insecure_cookie/testdata/insecure_cookie_session.js @@ -8,6 +8,7 @@ app.use(helmet()) app.use(helmet.hidePoweredBy()) app.use( +// bearer:expected javascript_express_insecure_cookie cookieSession({ domain: "example.com", httpOnly: false, diff --git a/tests/javascript/express/jwt_not_revoked/__snapshots__/test.js.snap b/tests/javascript/express/jwt_not_revoked/__snapshots__/test.js.snap deleted file mode 100644 index 71a39d7bb..000000000 --- a/tests/javascript/express/jwt_not_revoked/__snapshots__/test.js.snap +++ /dev/null @@ -1,187 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_jwt_not_revoked express_jwt_not_revoked 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_jwt_not_revoked", - "title": "Missing revoke method on JWT", - "description": "## Description\\nThe best practice caching policy is to revoke JWTs especially when these contain senstitive information.\\n\\n## Remediations\\n✅ Ensure JWTs are short-lived by revoking them\\n\\n\`\`\`javascript\\nexpressjwt({\\n ...\\n isRevoked: this.customRevokeCall(),\\n ...\\n})\\n\`\`\`\\n\\n## Resources\\n- [ExpressJWT documentation on revoking tokens](https://github.com/auth0/express-jwt#revoked-tokens)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_jwt_not_revoked", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/express_jwt_not_revoked.js", - "filename": ".", - "source": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 63 - } - }, - "sink": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 63 - }, - "content": "expressjwt({ secret: config.secret, algorithms: [\\"HS256\\"] })" - }, - "parent_line_number": 11, - "snippet": "expressjwt({ secret: config.secret, algorithms: [\\"HS256\\"] })", - "fingerprint": "eaae2a30ff6ed4568ddf01dd63a61387_0", - "old_fingerprint": "14c001b1dc34682262b42469b5f5fe84_0", - "code_extract": " expressjwt({ secret: config.secret, algorithms: [\\"HS256\\"] })," - }, - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_jwt_not_revoked", - "title": "Missing revoke method on JWT", - "description": "## Description\\nThe best practice caching policy is to revoke JWTs especially when these contain senstitive information.\\n\\n## Remediations\\n✅ Ensure JWTs are short-lived by revoking them\\n\\n\`\`\`javascript\\nexpressjwt({\\n ...\\n isRevoked: this.customRevokeCall(),\\n ...\\n})\\n\`\`\`\\n\\n## Resources\\n- [ExpressJWT documentation on revoking tokens](https://github.com/auth0/express-jwt#revoked-tokens)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_jwt_not_revoked", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/express_jwt_not_revoked.js", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 3, - "end": 63 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 3, - "end": 63 - }, - "content": "expressJwt({ secret: config.secret, algorithms: [\\"HS256\\"] })" - }, - "parent_line_number": 12, - "snippet": "expressJwt({ secret: config.secret, algorithms: [\\"HS256\\"] })", - "fingerprint": "eaae2a30ff6ed4568ddf01dd63a61387_1", - "old_fingerprint": "14c001b1dc34682262b42469b5f5fe84_1", - "code_extract": " expressJwt({ secret: config.secret, algorithms: [\\"HS256\\"] })," - }, - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_jwt_not_revoked", - "title": "Missing revoke method on JWT", - "description": "## Description\\nThe best practice caching policy is to revoke JWTs especially when these contain senstitive information.\\n\\n## Remediations\\n✅ Ensure JWTs are short-lived by revoking them\\n\\n\`\`\`javascript\\nexpressjwt({\\n ...\\n isRevoked: this.customRevokeCall(),\\n ...\\n})\\n\`\`\`\\n\\n## Resources\\n- [ExpressJWT documentation on revoking tokens](https://github.com/auth0/express-jwt#revoked-tokens)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_jwt_not_revoked", - "line_number": 13, - "full_filename": "/tmp/bearer-scan/express_jwt_not_revoked.js", - "filename": ".", - "source": { - "start": 13, - "end": 13, - "column": { - "start": 3, - "end": 63 - } - }, - "sink": { - "start": 13, - "end": 13, - "column": { - "start": 3, - "end": 63 - }, - "content": "ExpressJWT({ secret: config.secret, algorithms: [\\"HS256\\"] })" - }, - "parent_line_number": 13, - "snippet": "ExpressJWT({ secret: config.secret, algorithms: [\\"HS256\\"] })", - "fingerprint": "eaae2a30ff6ed4568ddf01dd63a61387_2", - "old_fingerprint": "14c001b1dc34682262b42469b5f5fe84_2", - "code_extract": " ExpressJWT({ secret: config.secret, algorithms: [\\"HS256\\"] })," - } - ] -}" -`; - -exports[`javascript_express_jwt_not_revoked insecurity_express_jwt_revoked 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_jwt_not_revoked", - "title": "Missing revoke method on JWT", - "description": "## Description\\nThe best practice caching policy is to revoke JWTs especially when these contain senstitive information.\\n\\n## Remediations\\n✅ Ensure JWTs are short-lived by revoking them\\n\\n\`\`\`javascript\\nexpressjwt({\\n ...\\n isRevoked: this.customRevokeCall(),\\n ...\\n})\\n\`\`\`\\n\\n## Resources\\n- [ExpressJWT documentation on revoking tokens](https://github.com/auth0/express-jwt#revoked-tokens)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_jwt_not_revoked", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/insecurity.ts", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 43 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 43 - }, - "content": "expressJwt({ secret: \\"\\" + Math.random() })" - }, - "parent_line_number": 1, - "snippet": "expressJwt({ secret: \\"\\" + Math.random() })", - "fingerprint": "eaae2a30ff6ed4568ddf01dd63a61387_0", - "old_fingerprint": "bc1db353c43740bf9d7b7d4bddbcddb4_0", - "code_extract": "expressJwt({ secret: \\"\\" + Math.random() })" - }, - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_jwt_not_revoked", - "title": "Missing revoke method on JWT", - "description": "## Description\\nThe best practice caching policy is to revoke JWTs especially when these contain senstitive information.\\n\\n## Remediations\\n✅ Ensure JWTs are short-lived by revoking them\\n\\n\`\`\`javascript\\nexpressjwt({\\n ...\\n isRevoked: this.customRevokeCall(),\\n ...\\n})\\n\`\`\`\\n\\n## Resources\\n- [ExpressJWT documentation on revoking tokens](https://github.com/auth0/express-jwt#revoked-tokens)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_jwt_not_revoked", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecurity.ts", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 30, - "end": 79 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 30, - "end": 79 - }, - "content": "expressjwt({ secret: \\"\\" + Math.random() } as any)" - }, - "parent_line_number": 2, - "snippet": "expressjwt({ secret: \\"\\" + Math.random() } as any)", - "fingerprint": "eaae2a30ff6ed4568ddf01dd63a61387_1", - "old_fingerprint": "bc1db353c43740bf9d7b7d4bddbcddb4_1", - "code_extract": "export const denyAll = () => expressjwt({ secret: \\"\\" + Math.random() } as any)" - } - ] -}" -`; - -exports[`javascript_express_jwt_not_revoked ok_express_jwt_revoked 1`] = `"{}"`; diff --git a/tests/javascript/express/jwt_not_revoked/test.js b/tests/javascript/express/jwt_not_revoked/test.js index fefc5f103..9d0e14336 100644 --- a/tests/javascript/express/jwt_not_revoked/test.js +++ b/tests/javascript/express/jwt_not_revoked/test.js @@ -1,21 +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) - - test("express_jwt_not_revoked", () => { - const testCase = "express_jwt_not_revoked.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("ok_express_jwt_revoked", () => { - const testCase = "ok_express_jwt_revoked.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("insecurity_express_jwt_revoked", () => { - const testCase = "insecurity.ts" - expect(invoke(testCase)).toMatchSnapshot() - }) -}) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + + test("express_jwt_not_revoked", () => { + const testCase = "express_jwt_not_revoked.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("insecurity", () => { + const testCase = "insecurity.ts" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("ok_express_jwt_revoked", () => { + const testCase = "ok_express_jwt_revoked.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + +}) \ No newline at end of file diff --git a/tests/javascript/express/jwt_not_revoked/testdata/express_jwt_not_revoked.js b/tests/javascript/express/jwt_not_revoked/testdata/express_jwt_not_revoked.js index 0370173c2..1ecf2caf2 100644 --- a/tests/javascript/express/jwt_not_revoked/testdata/express_jwt_not_revoked.js +++ b/tests/javascript/express/jwt_not_revoked/testdata/express_jwt_not_revoked.js @@ -8,8 +8,11 @@ app.use(helmet.hidePoweredBy()) app.get( "/unrevoked", +// bearer:expected javascript_express_jwt_not_revoked expressjwt({ secret: config.secret, algorithms: ["HS256"] }), +// bearer:expected javascript_express_jwt_not_revoked expressJwt({ secret: config.secret, algorithms: ["HS256"] }), +// bearer:expected javascript_express_jwt_not_revoked ExpressJWT({ secret: config.secret, algorithms: ["HS256"] }), function (req, res) { if (!req.auth.admin) return res.sendStatus(401) diff --git a/tests/javascript/express/jwt_not_revoked/testdata/insecurity.ts b/tests/javascript/express/jwt_not_revoked/testdata/insecurity.ts index 0359c4bab..6278d8901 100644 --- a/tests/javascript/express/jwt_not_revoked/testdata/insecurity.ts +++ b/tests/javascript/express/jwt_not_revoked/testdata/insecurity.ts @@ -1,2 +1,4 @@ +// bearer:expected javascript_express_jwt_not_revoked expressJwt({ secret: "" + Math.random() }) +// bearer:expected javascript_express_jwt_not_revoked export const denyAll = () => expressjwt({ secret: "" + Math.random() } as any) diff --git a/tests/javascript/express/open_redirect/__snapshots__/test.js.snap b/tests/javascript/express/open_redirect/__snapshots__/test.js.snap deleted file mode 100644 index 0a43aced2..000000000 --- a/tests/javascript/express/open_redirect/__snapshots__/test.js.snap +++ /dev/null @@ -1,146 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_open_redirect ok_no_open_redirect 1`] = `"{}"`; - -exports[`javascript_express_open_redirect open_redirect 1`] = ` -"{ - "medium": [ - { - "cwe_ids": [ - "601" - ], - "id": "javascript_express_open_redirect", - "title": "Unsanitized user input in redirect", - "description": "## Description\\nA redirect using unsanitized user input is bad practice and puts your application at greater risk of phishing attacks.\\n\\n## Remediations\\n❌ Do not use unsanitized user input when constructing URLs\\n\\n✅ Instead, ensure the input is validated by using a safe list or a mapping when constructing URLs\\n\\n\`\`\`javascript\\n var map = {\\n \\"1\\": \\"/planes\\",\\n \\"2\\": \\"/trains\\",\\n \\"3\\": \\"/automobiles\\",\\n }\\n\\n res.redirect(map[req.body.transport])\\n\`\`\`\\n## Resources\\n- [OWASP open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_open_redirect", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/open_redirect.js", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 3, - "end": 31 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 3, - "end": 31 - }, - "content": "res.redirect(req.params.url)" - }, - "parent_line_number": 2, - "snippet": "res.redirect(req.params.url)", - "fingerprint": "39fed10ce763bb1caf6ca1ea51314f28_0", - "old_fingerprint": "9b90ab18e9d910d91f630ff180293aed_0", - "code_extract": " res.redirect(req.params.url)" - }, - { - "cwe_ids": [ - "601" - ], - "id": "javascript_express_open_redirect", - "title": "Unsanitized user input in redirect", - "description": "## Description\\nA redirect using unsanitized user input is bad practice and puts your application at greater risk of phishing attacks.\\n\\n## Remediations\\n❌ Do not use unsanitized user input when constructing URLs\\n\\n✅ Instead, ensure the input is validated by using a safe list or a mapping when constructing URLs\\n\\n\`\`\`javascript\\n var map = {\\n \\"1\\": \\"/planes\\",\\n \\"2\\": \\"/trains\\",\\n \\"3\\": \\"/automobiles\\",\\n }\\n\\n res.redirect(map[req.body.transport])\\n\`\`\`\\n## Resources\\n- [OWASP open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_open_redirect", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/open_redirect.js", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 3, - "end": 39 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 3, - "end": 39 - }, - "content": "res.redirect(req.query.url + \\"/bar\\")" - }, - "parent_line_number": 3, - "snippet": "res.redirect(req.query.url + \\"/bar\\")", - "fingerprint": "39fed10ce763bb1caf6ca1ea51314f28_1", - "old_fingerprint": "9b90ab18e9d910d91f630ff180293aed_1", - "code_extract": " res.redirect(req.query.url + \\"/bar\\")" - }, - { - "cwe_ids": [ - "601" - ], - "id": "javascript_express_open_redirect", - "title": "Unsanitized user input in redirect", - "description": "## Description\\nA redirect using unsanitized user input is bad practice and puts your application at greater risk of phishing attacks.\\n\\n## Remediations\\n❌ Do not use unsanitized user input when constructing URLs\\n\\n✅ Instead, ensure the input is validated by using a safe list or a mapping when constructing URLs\\n\\n\`\`\`javascript\\n var map = {\\n \\"1\\": \\"/planes\\",\\n \\"2\\": \\"/trains\\",\\n \\"3\\": \\"/automobiles\\",\\n }\\n\\n res.redirect(map[req.body.transport])\\n\`\`\`\\n## Resources\\n- [OWASP open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_open_redirect", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/open_redirect.js", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 3, - "end": 53 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 3, - "end": 53 - }, - "content": "res.redirect(\\"https://\\" + req.params.url + \\"/bar\\")" - }, - "parent_line_number": 4, - "snippet": "res.redirect(\\"https://\\" + req.params.url + \\"/bar\\")", - "fingerprint": "39fed10ce763bb1caf6ca1ea51314f28_2", - "old_fingerprint": "9b90ab18e9d910d91f630ff180293aed_2", - "code_extract": " res.redirect(\\"https://\\" + req.params.url + \\"/bar\\")" - }, - { - "cwe_ids": [ - "601" - ], - "id": "javascript_express_open_redirect", - "title": "Unsanitized user input in redirect", - "description": "## Description\\nA redirect using unsanitized user input is bad practice and puts your application at greater risk of phishing attacks.\\n\\n## Remediations\\n❌ Do not use unsanitized user input when constructing URLs\\n\\n✅ Instead, ensure the input is validated by using a safe list or a mapping when constructing URLs\\n\\n\`\`\`javascript\\n var map = {\\n \\"1\\": \\"/planes\\",\\n \\"2\\": \\"/trains\\",\\n \\"3\\": \\"/automobiles\\",\\n }\\n\\n res.redirect(map[req.body.transport])\\n\`\`\`\\n## Resources\\n- [OWASP open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_open_redirect", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/open_redirect.js", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 3, - "end": 53 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 3, - "end": 53 - }, - "content": "res.redirect(\\"http://\\" + req.params.path + \\"/bar\\")" - }, - "parent_line_number": 5, - "snippet": "res.redirect(\\"http://\\" + req.params.path + \\"/bar\\")", - "fingerprint": "39fed10ce763bb1caf6ca1ea51314f28_3", - "old_fingerprint": "9b90ab18e9d910d91f630ff180293aed_3", - "code_extract": " res.redirect(\\"http://\\" + req.params.path + \\"/bar\\")" - } - ] -}" -`; diff --git a/tests/javascript/express/open_redirect/test.js b/tests/javascript/express/open_redirect/test.js index 1f3ce8820..44b7a75da 100644 --- a/tests/javascript/express/open_redirect/test.js +++ b/tests/javascript/express/open_redirect/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_no_open_redirect", () => { + const testCase = "ok_no_open_redirect.js" + + const results = invoke(testCase) - test("ok_no_open_redirect", () => { - const testCase = "ok_no_open_redirect.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("open_redirect", () => { - const testCase = "open_redirect.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("open_redirect", () => { + const testCase = "open_redirect.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/open_redirect/testdata/open_redirect.js b/tests/javascript/express/open_redirect/testdata/open_redirect.js index 6b7756a3b..9d197ec44 100644 --- a/tests/javascript/express/open_redirect/testdata/open_redirect.js +++ b/tests/javascript/express/open_redirect/testdata/open_redirect.js @@ -1,6 +1,10 @@ module.exports.foo = function(req, res){ +// bearer:expected javascript_express_open_redirect res.redirect(req.params.url) +// bearer:expected javascript_express_open_redirect res.redirect(req.query.url + "/bar") +// bearer:expected javascript_express_open_redirect res.redirect("https://" + req.params.url + "/bar") +// bearer:expected javascript_express_open_redirect res.redirect("http://" + req.params.path + "/bar") } diff --git a/tests/javascript/express/path_traversal/__snapshots__/test.js.snap b/tests/javascript/express/path_traversal/__snapshots__/test.js.snap deleted file mode 100644 index 0f41da42f..000000000 --- a/tests/javascript/express/path_traversal/__snapshots__/test.js.snap +++ /dev/null @@ -1,78 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_path_traversal ok_no_path_traversal_vulnerability 1`] = `"{}"`; - -exports[`javascript_express_path_traversal path_traversal_vulnerability 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "73" - ], - "id": "javascript_express_path_traversal", - "title": "Unsanitized user input in file path", - "description": "## Description\\nAllowing unsanitized user input in path resolution methods means an attacker could gain access to files and folders outside of the intended scope.\\n\\n## Remediations\\n❌ Avoid wherever possible\\n\\n✅ Sanitize user input when resolving paths, for example:\\n- Use \`replace()\` to mitigate against unwanted patterns in the path (such as \`\\\\..\\\\..\`)\\n- Actively guard against paths that end in \\"%00\\" (poison NULL byte attacks)\\n- Use path concatenation to ensure the intended scope is respected\\n\\n\`\`\`javascript\\nconst path = require(\\"path\\");\\n\\napp.get(\\"/\\", (req, res) => {\\n if (req.params.path.indexOf('\\\\0')) !== -1 {\\n // prevent access\\n }\\n\\n var folder = req.params.path.replace(/^(\\\\.\\\\.(\\\\/|\\\\\\\\|$))+/, '')\\n\\n var pathname = path.join(\\"/public/\\", folder)\\n if pathname.indexOf(\\"/public/\\") !== 0 {\\n // prevent access\\n }\\n\\n path.resolve(pathname)\\n})\\n\`\`\`\\n\\n## Resources\\n- [OWASP path traversal](https://owasp.org/www-community/attacks/Path_Traversal)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_path_traversal", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/path_traversal_vulnerability.js", - "filename": ".", - "source": { - "start": 9, - "end": 9, - "column": { - "start": 3, - "end": 40 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 3, - "end": 40 - }, - "content": "path.join(\\"/public/\\", req.query.path)" - }, - "parent_line_number": 9, - "snippet": "path.join(\\"/public/\\", req.query.path)", - "fingerprint": "a3f884b314acd58987c8feb137c54328_0", - "old_fingerprint": "41727c25af7e6cea2c383e214eff881f_0", - "code_extract": " path.join(\\"/public/\\", req.query.path)" - }, - { - "cwe_ids": [ - "73" - ], - "id": "javascript_express_path_traversal", - "title": "Unsanitized user input in file path", - "description": "## Description\\nAllowing unsanitized user input in path resolution methods means an attacker could gain access to files and folders outside of the intended scope.\\n\\n## Remediations\\n❌ Avoid wherever possible\\n\\n✅ Sanitize user input when resolving paths, for example:\\n- Use \`replace()\` to mitigate against unwanted patterns in the path (such as \`\\\\..\\\\..\`)\\n- Actively guard against paths that end in \\"%00\\" (poison NULL byte attacks)\\n- Use path concatenation to ensure the intended scope is respected\\n\\n\`\`\`javascript\\nconst path = require(\\"path\\");\\n\\napp.get(\\"/\\", (req, res) => {\\n if (req.params.path.indexOf('\\\\0')) !== -1 {\\n // prevent access\\n }\\n\\n var folder = req.params.path.replace(/^(\\\\.\\\\.(\\\\/|\\\\\\\\|$))+/, '')\\n\\n var pathname = path.join(\\"/public/\\", folder)\\n if pathname.indexOf(\\"/public/\\") !== 0 {\\n // prevent access\\n }\\n\\n path.resolve(pathname)\\n})\\n\`\`\`\\n\\n## Resources\\n- [OWASP path traversal](https://owasp.org/www-community/attacks/Path_Traversal)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_path_traversal", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/path_traversal_vulnerability.js", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 31 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 31 - }, - "content": "path.resolve(req.query.path)" - }, - "parent_line_number": 10, - "snippet": "path.resolve(req.query.path)", - "fingerprint": "a3f884b314acd58987c8feb137c54328_1", - "old_fingerprint": "41727c25af7e6cea2c383e214eff881f_1", - "code_extract": " path.resolve(req.query.path)" - } - ] -}" -`; diff --git a/tests/javascript/express/path_traversal/test.js b/tests/javascript/express/path_traversal/test.js index 6c4191e87..258ea9ee9 100644 --- a/tests/javascript/express/path_traversal/test.js +++ b/tests/javascript/express/path_traversal/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_no_path_traversal_vulnerability", () => { + const testCase = "ok_no_path_traversal_vulnerability.js" + + const results = invoke(testCase) - test("ok_no_path_traversal_vulnerability", () => { - const testCase = "ok_no_path_traversal_vulnerability.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("path_traversal_vulnerability", () => { - const testCase = "path_traversal_vulnerability.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("path_traversal_vulnerability", () => { + const testCase = "path_traversal_vulnerability.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/path_traversal/testdata/path_traversal_vulnerability.js b/tests/javascript/express/path_traversal/testdata/path_traversal_vulnerability.js index c65f0fcf5..9fa3de536 100644 --- a/tests/javascript/express/path_traversal/testdata/path_traversal_vulnerability.js +++ b/tests/javascript/express/path_traversal/testdata/path_traversal_vulnerability.js @@ -6,6 +6,8 @@ app.use(helmet()) app.use(helmet.hidePoweredBy()) app.get("/bad", (req, _res) => { +// bearer:expected javascript_express_path_traversal path.join("/public/", req.query.path) +// bearer:expected javascript_express_path_traversal path.resolve(req.query.path) }) diff --git a/tests/javascript/express/reduce_fingerprint/__snapshots__/test.js.snap b/tests/javascript/express/reduce_fingerprint/__snapshots__/test.js.snap deleted file mode 100644 index 28408cb39..000000000 --- a/tests/javascript/express/reduce_fingerprint/__snapshots__/test.js.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_reduce_fingerprint index 1`] = `"{}"`; - -exports[`javascript_express_reduce_fingerprint insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "693" - ], - "id": "javascript_express_reduce_fingerprint", - "title": "Missing server configuration to reduce server fingerprinting", - "description": "## Description\\n\\nIt can help to provide an extra layer of security to reduce server fingerprinting. Though not a security issue itself, a method to improve the overall posture of a web server is to take measures to reduce the ability to fingerprint the software being used on the server. Server software can be fingerprinted by quirks in how they respond to specific requests.\\n\\nBy default, Express.js sends the X-Powered-By response header banner. This can be disabled using the app.disable() method:\\n\\n\`\`\`javascript\\n app.disable('x-powered-by')\\n\`\`\`\\n\\n## Resources\\n\\n- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_reduce_fingerprint", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 13, - "end": 22 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 13, - "end": 22 - }, - "content": "express()" - }, - "parent_line_number": 4, - "snippet": "express()", - "fingerprint": "63781f2b12ffd9394ad7c9cc37302b37_0", - "old_fingerprint": "d847e2bd879ab5fe7844baa6b6480e12_0", - "code_extract": "const app = express()" - } - ] -}" -`; - -exports[`javascript_express_reduce_fingerprint secure_app_disable 1`] = `"{}"`; - -exports[`javascript_express_reduce_fingerprint secure_helmet 1`] = `"{}"`; - -exports[`javascript_express_reduce_fingerprint secure_helmet_import 1`] = `"{}"`; diff --git a/tests/javascript/express/reduce_fingerprint/test.js b/tests/javascript/express/reduce_fingerprint/test.js index 00516c8fd..177488a7b 100644 --- a/tests/javascript/express/reduce_fingerprint/test.js +++ b/tests/javascript/express/reduce_fingerprint/test.js @@ -1,37 +1,60 @@ -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("index", () => { + const testCase = "index.ts" + + const results = invoke(testCase) - test("index", () => { - const testCase = "index.ts" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure_app_disable", () => { - const testCase = "secure_app_disable.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure_app_disable", () => { + const testCase = "secure_app_disable.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure_helmet", () => { - const testCase = "secure_helmet.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure_helmet", () => { + const testCase = "secure_helmet.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure_helmet_import", () => { - const testCase = "secure_helmet_import.ts" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure_helmet_import", () => { + const testCase = "secure_helmet_import.ts" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/reduce_fingerprint/testdata/insecure.js b/tests/javascript/express/reduce_fingerprint/testdata/insecure.js index ee457a1cf..68cb112f4 100644 --- a/tests/javascript/express/reduce_fingerprint/testdata/insecure.js +++ b/tests/javascript/express/reduce_fingerprint/testdata/insecure.js @@ -1,6 +1,7 @@ const express = require("express") const cors = require("cors") +// bearer:expected javascript_express_reduce_fingerprint const app = express() app.use(express.json()) app.use(cors()) diff --git a/tests/javascript/express/server_side_request_forgery/__snapshots__/test.js.snap b/tests/javascript/express/server_side_request_forgery/__snapshots__/test.js.snap deleted file mode 100644 index 367958faa..000000000 --- a/tests/javascript/express/server_side_request_forgery/__snapshots__/test.js.snap +++ /dev/null @@ -1,160 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_server_side_request_forgery axios_ssrf_injection 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "918" - ], - "id": "javascript_express_server_side_request_forgery", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\nUsing unsanitized URLs from the request object when retrieving data puts your application at risk of server-side request forgery (SSRF) attacks.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in URLs:\\n\\n\`\`\`javascript\\naxios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nvar host = \\"default-api.com\\"\\nif req.params.host == \\"something-else\\" {\\n host = \\"other-api.com\\"\\n}\\n\\naxios.get(\`https://\${host}\`)\\n\`\`\`\\n\\n## Resources\\n- [OWASP - Server-Side Request Forgery (SSRF) prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_server_side_request_forgery", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/axios_ssrf_injection.js", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 28 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 3, - "end": 28 - }, - "content": "axios.get(req.query.path)" - }, - "parent_line_number": 10, - "snippet": "axios.get(req.query.path)", - "fingerprint": "2cac44cfde0c19367f3aa0fde6167679_0", - "old_fingerprint": "c94f877ee3e4e2c02a79e4bf25e012e6_0", - "code_extract": " axios.get(req.query.path).then((response) => res.json(response.data))" - } - ] -}" -`; - -exports[`javascript_express_server_side_request_forgery node_fetch_ssrf_injection 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "918" - ], - "id": "javascript_express_server_side_request_forgery", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\nUsing unsanitized URLs from the request object when retrieving data puts your application at risk of server-side request forgery (SSRF) attacks.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in URLs:\\n\\n\`\`\`javascript\\naxios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nvar host = \\"default-api.com\\"\\nif req.params.host == \\"something-else\\" {\\n host = \\"other-api.com\\"\\n}\\n\\naxios.get(\`https://\${host}\`)\\n\`\`\`\\n\\n## Resources\\n- [OWASP - Server-Side Request Forgery (SSRF) prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_server_side_request_forgery", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/node_fetch_ssrf_injection.js", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 20, - "end": 54 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 20, - "end": 54 - }, - "content": "fetch(\\"https://\\" + req.query.path)" - }, - "parent_line_number": 12, - "snippet": "fetch(\\"https://\\" + req.query.path)", - "fingerprint": "2cac44cfde0c19367f3aa0fde6167679_0", - "old_fingerprint": "dd939000e17001ab48d7c6a8eed78795_0", - "code_extract": " response = await fetch(\\"https://\\" + req.query.path)" - } - ] -}" -`; - -exports[`javascript_express_server_side_request_forgery ok_no_ssrf 1`] = `"{}"`; - -exports[`javascript_express_server_side_request_forgery puppeteer_ssrf_injection 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "918" - ], - "id": "javascript_express_server_side_request_forgery", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\nUsing unsanitized URLs from the request object when retrieving data puts your application at risk of server-side request forgery (SSRF) attacks.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in URLs:\\n\\n\`\`\`javascript\\naxios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nvar host = \\"default-api.com\\"\\nif req.params.host == \\"something-else\\" {\\n host = \\"other-api.com\\"\\n}\\n\\naxios.get(\`https://\${host}\`)\\n\`\`\`\\n\\n## Resources\\n- [OWASP - Server-Side Request Forgery (SSRF) prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_server_side_request_forgery", - "line_number": 15, - "full_filename": "/tmp/bearer-scan/puppeteer_ssrf_injection.js", - "filename": ".", - "source": { - "start": 15, - "end": 15, - "column": { - "start": 9, - "end": 33 - } - }, - "sink": { - "start": 15, - "end": 15, - "column": { - "start": 9, - "end": 33 - }, - "content": "page.setContent(content)" - }, - "parent_line_number": 15, - "snippet": "page.setContent(content)", - "fingerprint": "2cac44cfde0c19367f3aa0fde6167679_0", - "old_fingerprint": "b491f2bf9c290ee7c8845af36dd58aa6_0", - "code_extract": " await page.setContent(content)" - }, - { - "cwe_ids": [ - "918" - ], - "id": "javascript_express_server_side_request_forgery", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\nUsing unsanitized URLs from the request object when retrieving data puts your application at risk of server-side request forgery (SSRF) attacks.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in URLs:\\n\\n\`\`\`javascript\\naxios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nvar host = \\"default-api.com\\"\\nif req.params.host == \\"something-else\\" {\\n host = \\"other-api.com\\"\\n}\\n\\naxios.get(\`https://\${host}\`)\\n\`\`\`\\n\\n## Resources\\n- [OWASP - Server-Side Request Forgery (SSRF) prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_server_side_request_forgery", - "line_number": 16, - "full_filename": "/tmp/bearer-scan/puppeteer_ssrf_injection.js", - "filename": ".", - "source": { - "start": 16, - "end": 16, - "column": { - "start": 9, - "end": 47 - } - }, - "sink": { - "start": 16, - "end": 16, - "column": { - "start": 9, - "end": 47 - }, - "content": "page.goto(\\"https://\\" + req.query.path)" - }, - "parent_line_number": 16, - "snippet": "page.goto(\\"https://\\" + req.query.path)", - "fingerprint": "2cac44cfde0c19367f3aa0fde6167679_1", - "old_fingerprint": "b491f2bf9c290ee7c8845af36dd58aa6_1", - "code_extract": " await page.goto(\\"https://\\" + req.query.path)" - } - ] -}" -`; diff --git a/tests/javascript/express/server_side_request_forgery/test.js b/tests/javascript/express/server_side_request_forgery/test.js index aeca5c1bf..d00a399cc 100644 --- a/tests/javascript/express/server_side_request_forgery/test.js +++ b/tests/javascript/express/server_side_request_forgery/test.js @@ -1,31 +1,50 @@ -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("axios_ssrf_injection", () => { + const testCase = "axios_ssrf_injection.js" + + const results = invoke(testCase) - test("axios_ssrf_injection", () => { - const testCase = "axios_ssrf_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("node_fetch_ssrf_injection", () => { - const testCase = "node_fetch_ssrf_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("node_fetch_ssrf_injection", () => { + const testCase = "node_fetch_ssrf_injection.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_no_ssrf", () => { - const testCase = "ok_no_ssrf.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_no_ssrf", () => { + const testCase = "ok_no_ssrf.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("puppeteer_ssrf_injection", () => { - const testCase = "puppeteer_ssrf_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("puppeteer_ssrf_injection", () => { + const testCase = "puppeteer_ssrf_injection.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/server_side_request_forgery/testdata/axios_ssrf_injection.js b/tests/javascript/express/server_side_request_forgery/testdata/axios_ssrf_injection.js index f4fdee745..06b9774f1 100644 --- a/tests/javascript/express/server_side_request_forgery/testdata/axios_ssrf_injection.js +++ b/tests/javascript/express/server_side_request_forgery/testdata/axios_ssrf_injection.js @@ -7,5 +7,6 @@ app.use(helmet()) app.use(helmet.hidePoweredBy()) app.get("/inject", async (req, res) => { +// bearer:expected javascript_express_server_side_request_forgery axios.get(req.query.path).then((response) => res.json(response.data)) }) diff --git a/tests/javascript/express/server_side_request_forgery/testdata/node_fetch_ssrf_injection.js b/tests/javascript/express/server_side_request_forgery/testdata/node_fetch_ssrf_injection.js index 9a582bbb5..0f6da764d 100644 --- a/tests/javascript/express/server_side_request_forgery/testdata/node_fetch_ssrf_injection.js +++ b/tests/javascript/express/server_side_request_forgery/testdata/node_fetch_ssrf_injection.js @@ -9,6 +9,7 @@ app.use(helmet.hidePoweredBy()) const app = express() app.get("/inject", async (req, res) => { +// bearer:expected javascript_express_server_side_request_forgery response = await fetch("https://" + req.query.path) res.json(response.data) }) diff --git a/tests/javascript/express/server_side_request_forgery/testdata/puppeteer_ssrf_injection.js b/tests/javascript/express/server_side_request_forgery/testdata/puppeteer_ssrf_injection.js index d8458e0f1..8bc83a519 100644 --- a/tests/javascript/express/server_side_request_forgery/testdata/puppeteer_ssrf_injection.js +++ b/tests/javascript/express/server_side_request_forgery/testdata/puppeteer_ssrf_injection.js @@ -12,7 +12,9 @@ app.get("/inject", async (req, res) => { const page = await browser.newPage() var content = req.body.content +// bearer:expected javascript_express_server_side_request_forgery await page.setContent(content) +// bearer:expected javascript_express_server_side_request_forgery await page.goto("https://" + req.query.path) res.send("success") diff --git a/tests/javascript/express/static_asset_with_session/__snapshots__/test.js.snap b/tests/javascript/express/static_asset_with_session/__snapshots__/test.js.snap deleted file mode 100644 index d2d301809..000000000 --- a/tests/javascript/express/static_asset_with_session/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_static_asset_with_session ok 1`] = `"{}"`; - -exports[`javascript_express_static_asset_with_session unsafe 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "352" - ], - "id": "javascript_express_static_asset_with_session", - "title": "Usage of session on static asset (CSRF)", - "description": "## Description\\nStatic assets are often cached by services in front of the application\\n(eg. CDNs). Serving static assets with sessions enabled may lead to\\nCross-Site Request Forgery (CSRF) attacks that can hijack a user's session.\\n\\n## Remediations\\n\\n✅ Ensure static resources are handled prior to session initialization:\\n\\n\`\`\`javascript\\n // static middleware should be added before session middleware\\n app.use(express.static(__dirname + \\"/public\\"))\\n\\n app.use(session())\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_static_asset_with_session", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/unsafe.js", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 47 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 47 - }, - "content": "app.use(express.static(__dirname + \\"/public\\"))" - }, - "parent_line_number": 3, - "snippet": "app.use(express.static(__dirname + \\"/public\\"))", - "fingerprint": "602559f0bc1d3e94565f9bd2eeed56ca_0", - "old_fingerprint": "62d68eea63378ca9d5adbf7d5c39ca1c_0", - "code_extract": "app.use(express.static(__dirname + \\"/public\\"))" - } - ] -}" -`; diff --git a/tests/javascript/express/static_asset_with_session/test.js b/tests/javascript/express/static_asset_with_session/test.js index 50df017a4..d3713f024 100644 --- a/tests/javascript/express/static_asset_with_session/test.js +++ b/tests/javascript/express/static_asset_with_session/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.js" + + const results = invoke(testCase) - test("ok", () => { - const testCase = "ok.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("unsafe", () => { - const testCase = "unsafe.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("unsafe", () => { + const testCase = "unsafe.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/static_asset_with_session/testdata/unsafe.js b/tests/javascript/express/static_asset_with_session/testdata/unsafe.js index 0c10a6527..5d960560c 100644 --- a/tests/javascript/express/static_asset_with_session/testdata/unsafe.js +++ b/tests/javascript/express/static_asset_with_session/testdata/unsafe.js @@ -1,3 +1,4 @@ app.use(session({})) app.use(other()) +// bearer:expected javascript_express_static_asset_with_session app.use(express.static(__dirname + "/public")) diff --git a/tests/javascript/express/ui_redress/__snapshots__/test.js.snap b/tests/javascript/express/ui_redress/__snapshots__/test.js.snap deleted file mode 100644 index 5f5387961..000000000 --- a/tests/javascript/express/ui_redress/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_ui_redress ok_no_ui_redress 1`] = `"{}"`; - -exports[`javascript_express_ui_redress ui_redress_vulnerability 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "1021" - ], - "id": "javascript_express_ui_redress", - "title": "Unsanitized user input in UI", - "description": "## Description\\nUsing unsanitized user input to set X-Frame-Options or Content-Security-Policy HTTP headers puts your application at risk for UI redress attacks (clickjacking).\\n\\n## Remediations\\n✅ Prefer the most secure values when setting these headers\\n\\n\`\`\`javascript\\nres.set('X-Frame-Options', 'DENY')\\nres.set('Content-Security-Policy', \\"frame-ancestors 'none'\\")\\n\`\`\`\\n\\n✅ Avoid using user input directly to set the headers, or use a safelist to guard against clickjacking\\n\\n\`\`\`javascript\\nif (req.query.options === 'same') {\\n res.set('X-Frame-Options', 'SAME')\\n}\\n\\n// safelist\\nif (['deny', 'sameorigin'].includes(req.query.options.toLowerCase)) {\\n res.set('X-Frame-Options', req.query.options)\\n}\\n\`\`\`\\n\\n## Resources\\n- [OWASP Clickjacking attack explained](https://owasp.org/www-community/attacks/Clickjacking)\\n- [OWASP Clickjacking defense cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_ui_redress", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/ui_redress_vulnerability.js", - "filename": ".", - "source": { - "start": 9, - "end": 9, - "column": { - "start": 3, - "end": 48 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 3, - "end": 48 - }, - "content": "res.set(\\"X-Frame-Options\\", req.query.options)" - }, - "parent_line_number": 9, - "snippet": "res.set(\\"X-Frame-Options\\", req.query.options)", - "fingerprint": "b40f739a8e41b1f282e8933e44d85b5b_0", - "old_fingerprint": "5ec2d95d1c9df152e461eee42bb653ff_0", - "code_extract": " res.set(\\"X-Frame-Options\\", req.query.options)" - } - ] -}" -`; diff --git a/tests/javascript/express/ui_redress/test.js b/tests/javascript/express/ui_redress/test.js index 16259c8bf..e3ea56f98 100644 --- a/tests/javascript/express/ui_redress/test.js +++ b/tests/javascript/express/ui_redress/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_no_ui_redress", () => { + const testCase = "ok_no_ui_redress.js" + + const results = invoke(testCase) - test("ok_no_ui_redress", () => { - const testCase = "ok_no_ui_redress.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ui_redress_vulnerability", () => { - const testCase = "ui_redress_vulnerability.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ui_redress_vulnerability", () => { + const testCase = "ui_redress_vulnerability.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/ui_redress/testdata/ui_redress_vulnerability.js b/tests/javascript/express/ui_redress/testdata/ui_redress_vulnerability.js index 63e3dcf54..5fe9c60c2 100644 --- a/tests/javascript/express/ui_redress/testdata/ui_redress_vulnerability.js +++ b/tests/javascript/express/ui_redress/testdata/ui_redress_vulnerability.js @@ -6,6 +6,7 @@ app.use(helmet()) app.disable("x-powered-by") app.get("/bad", (req, res) => { +// bearer:expected javascript_express_ui_redress res.set("X-Frame-Options", req.query.options) res.send(200) }) diff --git a/tests/javascript/express/unsafe_deserialization/__snapshots__/test.js.snap b/tests/javascript/express/unsafe_deserialization/__snapshots__/test.js.snap deleted file mode 100644 index 4880eb54e..000000000 --- a/tests/javascript/express/unsafe_deserialization/__snapshots__/test.js.snap +++ /dev/null @@ -1,85 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_unsafe_deserialization node_serialize 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "502" - ], - "id": "javascript_express_unsafe_deserialization", - "title": "Unsanitized user input in deserialization method", - "description": "## Description\\nIt is bad practice to deserialize (unmarshal) untrusted data, such as data direct from the request object.\\nAttackers can transfer payloads or malicious code via serialized data, and deserializing such data puts your application at risk.\\n\\n## Remediations\\n❌ Do not deserialize untrusted data\\n\\n✅ Prefer pure (data-only) and language-agnostic (de)serialization formats such as JSON or XML\\n\\nAvoiding language-specific (de)serialization formats reduces the risk of attackers manipulating the deserialization process for malicious purposes.\\n\\n\`\`\`javascript\\n JSON.parse(req.params)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Deserialization cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_unsafe_deserialization", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/node_serialize.js", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 3, - "end": 37 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 3, - "end": 37 - }, - "content": "nodeSerialize.unserialize(userStr)" - }, - "parent_line_number": 5, - "snippet": "nodeSerialize.unserialize(userStr)", - "fingerprint": "8344d2cb0faaa6ea9f5e63d59dac105b_0", - "old_fingerprint": "562850de5efefc0b1924b72570005361_0", - "code_extract": " nodeSerialize.unserialize(userStr)" - } - ] -}" -`; - -exports[`javascript_express_unsafe_deserialization ok_safe_deserialization 1`] = `"{}"`; - -exports[`javascript_express_unsafe_deserialization serialize_error 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "502" - ], - "id": "javascript_express_unsafe_deserialization", - "title": "Unsanitized user input in deserialization method", - "description": "## Description\\nIt is bad practice to deserialize (unmarshal) untrusted data, such as data direct from the request object.\\nAttackers can transfer payloads or malicious code via serialized data, and deserializing such data puts your application at risk.\\n\\n## Remediations\\n❌ Do not deserialize untrusted data\\n\\n✅ Prefer pure (data-only) and language-agnostic (de)serialization formats such as JSON or XML\\n\\nAvoiding language-specific (de)serialization formats reduces the risk of attackers manipulating the deserialization process for malicious purposes.\\n\\n\`\`\`javascript\\n JSON.parse(req.params)\\n\`\`\`\\n\\n## Resources\\n- [OWASP Deserialization cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_unsafe_deserialization", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/serialize_error.js", - "filename": ".", - "source": { - "start": 4, - "end": 7, - "column": { - "start": 3, - "end": 5 - } - }, - "sink": { - "start": 4, - "end": 7, - "column": { - "start": 3, - "end": 5 - }, - "content": "deserializeError({\\n name: \\"MyCustomError\\",\\n message: req.params.error\\n })" - }, - "parent_line_number": 4, - "snippet": "deserializeError({\\n name: \\"MyCustomError\\",\\n message: req.params.error\\n })", - "fingerprint": "8344d2cb0faaa6ea9f5e63d59dac105b_0", - "old_fingerprint": "84d0cb074d10cd54e16d62f4b9fd99ed_0", - "code_extract": " deserializeError({\\n name: \\"MyCustomError\\",\\n message: req.params.error\\n })" - } - ] -}" -`; diff --git a/tests/javascript/express/unsafe_deserialization/test.js b/tests/javascript/express/unsafe_deserialization/test.js index 8c563fbde..56e5535bf 100644 --- a/tests/javascript/express/unsafe_deserialization/test.js +++ b/tests/javascript/express/unsafe_deserialization/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("node_serialize", () => { + const testCase = "node_serialize.js" + + const results = invoke(testCase) - test("node_serialize", () => { - const testCase = "node_serialize.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_safe_deserialization", () => { - const testCase = "ok_safe_deserialization.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_safe_deserialization", () => { + const testCase = "ok_safe_deserialization.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("serialize_error", () => { - const testCase = "serialize_error.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("serialize_error", () => { + const testCase = "serialize_error.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/unsafe_deserialization/testdata/node_serialize.js b/tests/javascript/express/unsafe_deserialization/testdata/node_serialize.js index 198f3a577..3e32663ca 100644 --- a/tests/javascript/express/unsafe_deserialization/testdata/node_serialize.js +++ b/tests/javascript/express/unsafe_deserialization/testdata/node_serialize.js @@ -2,5 +2,6 @@ var nodeSerialize = require("node-serialize") module.exports.unsafeDeserialize = function(req, _res){ var userStr = new Buffer.from(req.cookies.user, "utf8").toString(); +// bearer:expected javascript_express_unsafe_deserialization nodeSerialize.unserialize(userStr) } diff --git a/tests/javascript/express/unsafe_deserialization/testdata/serialize_error.js b/tests/javascript/express/unsafe_deserialization/testdata/serialize_error.js index 805cb4e63..e8dd3ca7b 100644 --- a/tests/javascript/express/unsafe_deserialization/testdata/serialize_error.js +++ b/tests/javascript/express/unsafe_deserialization/testdata/serialize_error.js @@ -1,6 +1,7 @@ import deserializeError from 'serialize-error'; module.exports.deserializedError = function(req, _res) { +// bearer:expected javascript_express_unsafe_deserialization deserializeError({ name: "MyCustomError", message: req.params.error diff --git a/tests/javascript/express/xml_external_entity_vulnerability/__snapshots__/test.js.snap b/tests/javascript/express/xml_external_entity_vulnerability/__snapshots__/test.js.snap deleted file mode 100644 index e484fd235..000000000 --- a/tests/javascript/express/xml_external_entity_vulnerability/__snapshots__/test.js.snap +++ /dev/null @@ -1,169 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_express_xml_external_entity_vulnerability lib_xml_with_noent_true 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "611" - ], - "id": "javascript_express_xml_external_entity_vulnerability", - "title": "Unsanitized user input in XML parsing method", - "description": "## Description\\nAvoid parsing untrusted data as XML. Such data could include URIs that resolve to resources that are outside of the current context, leading to XML External Entity (XXE) injection.\\n\\n## Remediations\\n❌ Do not enable parsing of external entities.\\n\\nFor LibXML, for example, do not set \`noent\` to \`true\`.\\n\`\`\`javascript\\n var libxml = require(\\"libxmljs\\");\\n libxml.parseXmlString(xml, { noent: true, noblanks: true });\\n\`\`\`\\n\\n## Resources\\n- [OWASP XML External Entity (XXE) prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_xml_external_entity_vulnerability", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/lib_xml_with_noent_true.js", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 30, - "end": 41 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 30, - "end": 41 - }, - "content": "noent: true" - }, - "parent_line_number": 4, - "snippet": "noent: true", - "fingerprint": "aeddcc748b5741b64a0bae9b6e6aee06_0", - "old_fingerprint": "6bc9351ee0ec6da80a5da07054561f88_0", - "code_extract": "libxml.parseXmlString(xml, { noent: true, noblanks: true });" - } - ] -}" -`; - -exports[`javascript_express_xml_external_entity_vulnerability ok_lib_xml_with_noent_false 1`] = `"{}"`; - -exports[`javascript_express_xml_external_entity_vulnerability ok_no_xxe_vuln_present 1`] = `"{}"`; - -exports[`javascript_express_xml_external_entity_vulnerability xxe_vuln_with_node_expat 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "611" - ], - "id": "javascript_express_xml_external_entity_vulnerability", - "title": "Unsanitized user input in XML parsing method", - "description": "## Description\\nAvoid parsing untrusted data as XML. Such data could include URIs that resolve to resources that are outside of the current context, leading to XML External Entity (XXE) injection.\\n\\n## Remediations\\n❌ Do not enable parsing of external entities.\\n\\nFor LibXML, for example, do not set \`noent\` to \`true\`.\\n\`\`\`javascript\\n var libxml = require(\\"libxmljs\\");\\n libxml.parseXmlString(xml, { noent: true, noblanks: true });\\n\`\`\`\\n\\n## Resources\\n- [OWASP XML External Entity (XXE) prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_xml_external_entity_vulnerability", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/xxe_vuln_with_node_expat.js", - "filename": ".", - "source": { - "start": 6, - "end": 6, - "column": { - "start": 3, - "end": 37 - } - }, - "sink": { - "start": 6, - "end": 6, - "column": { - "start": 3, - "end": 37 - }, - "content": "parser.parse(req.body.user, false)" - }, - "parent_line_number": 6, - "snippet": "parser.parse(req.body.user, false)", - "fingerprint": "aeddcc748b5741b64a0bae9b6e6aee06_0", - "old_fingerprint": "fb615134e46dedb3f5cce48f482bb597_0", - "code_extract": " parser.parse(req.body.user, false)" - } - ] -}" -`; - -exports[`javascript_express_xml_external_entity_vulnerability xxe_vuln_with_xml2js 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "611" - ], - "id": "javascript_express_xml_external_entity_vulnerability", - "title": "Unsanitized user input in XML parsing method", - "description": "## Description\\nAvoid parsing untrusted data as XML. Such data could include URIs that resolve to resources that are outside of the current context, leading to XML External Entity (XXE) injection.\\n\\n## Remediations\\n❌ Do not enable parsing of external entities.\\n\\nFor LibXML, for example, do not set \`noent\` to \`true\`.\\n\`\`\`javascript\\n var libxml = require(\\"libxmljs\\");\\n libxml.parseXmlString(xml, { noent: true, noblanks: true });\\n\`\`\`\\n\\n## Resources\\n- [OWASP XML External Entity (XXE) prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_xml_external_entity_vulnerability", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/xxe_vuln_with_xml2js.js", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 3, - "end": 64 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 3, - "end": 64 - }, - "content": "parser.parseString(req.body.data, function(_err, _result) {})" - }, - "parent_line_number": 5, - "snippet": "parser.parseString(req.body.data, function(_err, _result) {})", - "fingerprint": "aeddcc748b5741b64a0bae9b6e6aee06_0", - "old_fingerprint": "8da759e02b8f37a9385b887a7495ba2b_0", - "code_extract": " parser.parseString(req.body.data, function(_err, _result) {})" - } - ] -}" -`; - -exports[`javascript_express_xml_external_entity_vulnerability xxe_vuln_with_xml2json 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "611" - ], - "id": "javascript_express_xml_external_entity_vulnerability", - "title": "Unsanitized user input in XML parsing method", - "description": "## Description\\nAvoid parsing untrusted data as XML. Such data could include URIs that resolve to resources that are outside of the current context, leading to XML External Entity (XXE) injection.\\n\\n## Remediations\\n❌ Do not enable parsing of external entities.\\n\\nFor LibXML, for example, do not set \`noent\` to \`true\`.\\n\`\`\`javascript\\n var libxml = require(\\"libxmljs\\");\\n libxml.parseXmlString(xml, { noent: true, noblanks: true });\\n\`\`\`\\n\\n## Resources\\n- [OWASP XML External Entity (XXE) prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_express_xml_external_entity_vulnerability", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/xxe_vuln_with_xml2json.js", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 10, - "end": 54 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 10, - "end": 54 - }, - "content": "parser.toXml(req.body, { ignoreNull: true })" - }, - "parent_line_number": 4, - "snippet": "parser.toXml(req.body, { ignoreNull: true })", - "fingerprint": "aeddcc748b5741b64a0bae9b6e6aee06_0", - "old_fingerprint": "280adc54125f04430aac02e0611e9291_0", - "code_extract": " return parser.toXml(req.body, { ignoreNull: true })" - } - ] -}" -`; diff --git a/tests/javascript/express/xml_external_entity_vulnerability/test.js b/tests/javascript/express/xml_external_entity_vulnerability/test.js index c9fa7ce43..e41adbbc4 100644 --- a/tests/javascript/express/xml_external_entity_vulnerability/test.js +++ b/tests/javascript/express/xml_external_entity_vulnerability/test.js @@ -1,43 +1,70 @@ -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("lib_xml_with_noent_true", () => { + const testCase = "lib_xml_with_noent_true.js" + + const results = invoke(testCase) - test("lib_xml_with_noent_true", () => { - const testCase = "lib_xml_with_noent_true.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_lib_xml_with_noent_false", () => { - const testCase = "ok_lib_xml_with_noent_false.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_lib_xml_with_noent_false", () => { + const testCase = "ok_lib_xml_with_noent_false.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_no_xxe_vuln_present", () => { - const testCase = "ok_no_xxe_vuln_present.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_no_xxe_vuln_present", () => { + const testCase = "ok_no_xxe_vuln_present.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("xxe_vuln_with_node_expat", () => { - const testCase = "xxe_vuln_with_node_expat.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("xxe_vuln_with_node_expat", () => { + const testCase = "xxe_vuln_with_node_expat.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("xxe_vuln_with_xml2js", () => { - const testCase = "xxe_vuln_with_xml2js.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("xxe_vuln_with_xml2js", () => { + const testCase = "xxe_vuln_with_xml2js.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("xxe_vuln_with_xml2json", () => { - const testCase = "xxe_vuln_with_xml2json.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("xxe_vuln_with_xml2json", () => { + const testCase = "xxe_vuln_with_xml2json.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/express/xml_external_entity_vulnerability/testdata/lib_xml_with_noent_true.js b/tests/javascript/express/xml_external_entity_vulnerability/testdata/lib_xml_with_noent_true.js index 2ef986209..98fcb6fb9 100644 --- a/tests/javascript/express/xml_external_entity_vulnerability/testdata/lib_xml_with_noent_true.js +++ b/tests/javascript/express/xml_external_entity_vulnerability/testdata/lib_xml_with_noent_true.js @@ -1,4 +1,5 @@ var libxml = require("libxmljs"); var xml = ''; +// bearer:expected javascript_express_xml_external_entity_vulnerability libxml.parseXmlString(xml, { noent: true, noblanks: true }); \ No newline at end of file diff --git a/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_node_expat.js b/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_node_expat.js index 0c7b94f89..781b533e7 100644 --- a/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_node_expat.js +++ b/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_node_expat.js @@ -3,5 +3,6 @@ import expat from 'node-expat'; module.exports.parseXML = function(req, _res) { const parser = new expat.Parser() +// bearer:expected javascript_express_xml_external_entity_vulnerability parser.parse(req.body.user, false) } diff --git a/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_xml2js.js b/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_xml2js.js index b8ed4b3c7..3fd40f6b0 100644 --- a/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_xml2js.js +++ b/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_xml2js.js @@ -2,5 +2,6 @@ import xml2js from 'xml2js'; module.exports.parseXML = function(req, _res) { var parser = new xml2js.Parser() +// bearer:expected javascript_express_xml_external_entity_vulnerability parser.parseString(req.body.data, function(_err, _result) {}) } diff --git a/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_xml2json.js b/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_xml2json.js index cb0eab3cd..f1d19e303 100644 --- a/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_xml2json.js +++ b/tests/javascript/express/xml_external_entity_vulnerability/testdata/xxe_vuln_with_xml2json.js @@ -1,5 +1,6 @@ import parser from 'xml2json'; module.exports.parseXML = function(req, _res) { +// bearer:expected javascript_express_xml_external_entity_vulnerability return parser.toXml(req.body, { ignoreNull: true }) } diff --git a/tests/javascript/lang/dangerous_insert_html/__snapshots__/test.js.snap b/tests/javascript/lang/dangerous_insert_html/__snapshots__/test.js.snap deleted file mode 100644 index ea454711b..000000000 --- a/tests/javascript/lang/dangerous_insert_html/__snapshots__/test.js.snap +++ /dev/null @@ -1,228 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_dangerous_insert_html insecure-document_write 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_dangerous_insert_html", - "title": "Unsanitized user input in dynamic HTML insertion (XSS)", - "description": "## Description\\nThere are XSS vulnerabilities when dynamically inserting HTML that contains unsanitized data.\\n\\n## Remediations\\nMake sure you use HTML sanitization library before inserting html\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html';\\n\\nconst html = \`\${user.Input}\`;\\ndocument.body.innerHTML = sanitizeHtml(html)\\n\`\`\`\\n\\n## Resources\\n- [OWASP XSS explained](https://owasp.org/www-community/attacks/xss/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_dangerous_insert_html", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure-document_write.js", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 3, - "end": 38 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 3, - "end": 38 - }, - "content": "document.write(\`
  • \${input}
  • \`)" - }, - "parent_line_number": 2, - "snippet": "document.write(\`
  • \${input}
  • \`)", - "fingerprint": "315770dda0d4ea464e59f5bd073bd950_0", - "old_fingerprint": "f2715af76f6b84d2f19052ee9292d9e3_0", - "code_extract": " document.write(\`
  • \${input}
  • \`)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_dangerous_insert_html", - "title": "Unsanitized user input in dynamic HTML insertion (XSS)", - "description": "## Description\\nThere are XSS vulnerabilities when dynamically inserting HTML that contains unsanitized data.\\n\\n## Remediations\\nMake sure you use HTML sanitization library before inserting html\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html';\\n\\nconst html = \`\${user.Input}\`;\\ndocument.body.innerHTML = sanitizeHtml(html)\\n\`\`\`\\n\\n## Resources\\n- [OWASP XSS explained](https://owasp.org/www-community/attacks/xss/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_dangerous_insert_html", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/insecure-document_write.js", - "filename": ".", - "source": { - "start": 8, - "end": 8, - "column": { - "start": 3, - "end": 48 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 3, - "end": 48 - }, - "content": "el.innerHTML = \\"
    \\" + userInput + \\"
    \\"" - }, - "parent_line_number": 8, - "snippet": "el.innerHTML = \\"
    \\" + userInput + \\"
    \\"", - "fingerprint": "315770dda0d4ea464e59f5bd073bd950_1", - "old_fingerprint": "f2715af76f6b84d2f19052ee9292d9e3_1", - "code_extract": " el.innerHTML = \\"
    \\" + userInput + \\"
    \\"" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_dangerous_insert_html", - "title": "Unsanitized user input in dynamic HTML insertion (XSS)", - "description": "## Description\\nThere are XSS vulnerabilities when dynamically inserting HTML that contains unsanitized data.\\n\\n## Remediations\\nMake sure you use HTML sanitization library before inserting html\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html';\\n\\nconst html = \`\${user.Input}\`;\\ndocument.body.innerHTML = sanitizeHtml(html)\\n\`\`\`\\n\\n## Resources\\n- [OWASP XSS explained](https://owasp.org/www-community/attacks/xss/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_dangerous_insert_html", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/insecure-document_write.js", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 3, - "end": 38 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 3, - "end": 38 - }, - "content": "document.body.outerHTML = userInput" - }, - "parent_line_number": 12, - "snippet": "document.body.outerHTML = userInput", - "fingerprint": "315770dda0d4ea464e59f5bd073bd950_2", - "old_fingerprint": "f2715af76f6b84d2f19052ee9292d9e3_2", - "code_extract": " document.body.outerHTML = userInput" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_dangerous_insert_html", - "title": "Unsanitized user input in dynamic HTML insertion (XSS)", - "description": "## Description\\nThere are XSS vulnerabilities when dynamically inserting HTML that contains unsanitized data.\\n\\n## Remediations\\nMake sure you use HTML sanitization library before inserting html\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html';\\n\\nconst html = \`\${user.Input}\`;\\ndocument.body.innerHTML = sanitizeHtml(html)\\n\`\`\`\\n\\n## Resources\\n- [OWASP XSS explained](https://owasp.org/www-community/attacks/xss/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_dangerous_insert_html", - "line_number": 17, - "full_filename": "/tmp/bearer-scan/insecure-document_write.js", - "filename": ".", - "source": { - "start": 17, - "end": 17, - "column": { - "start": 3, - "end": 23 - } - }, - "sink": { - "start": 17, - "end": 17, - "column": { - "start": 3, - "end": 23 - }, - "content": "document.write(name)" - }, - "parent_line_number": 17, - "snippet": "document.write(name)", - "fingerprint": "315770dda0d4ea464e59f5bd073bd950_3", - "old_fingerprint": "f2715af76f6b84d2f19052ee9292d9e3_3", - "code_extract": " document.write(name)" - } - ] -}" -`; - -exports[`javascript_lang_dangerous_insert_html insecure-element_ref 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_dangerous_insert_html", - "title": "Unsanitized user input in dynamic HTML insertion (XSS)", - "description": "## Description\\nThere are XSS vulnerabilities when dynamically inserting HTML that contains unsanitized data.\\n\\n## Remediations\\nMake sure you use HTML sanitization library before inserting html\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html';\\n\\nconst html = \`\${user.Input}\`;\\ndocument.body.innerHTML = sanitizeHtml(html)\\n\`\`\`\\n\\n## Resources\\n- [OWASP XSS explained](https://owasp.org/www-community/attacks/xss/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_dangerous_insert_html", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure-element_ref.js", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 2, - "end": 47 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 2, - "end": 47 - }, - "content": "this.ref.replaceChildren(\`
  • \${input}
  • \`)" - }, - "parent_line_number": 2, - "snippet": "this.ref.replaceChildren(\`
  • \${input}
  • \`)", - "fingerprint": "315770dda0d4ea464e59f5bd073bd950_0", - "old_fingerprint": "77aaf3a9264049dc97cafbd34be6192b_0", - "code_extract": "\\tthis.ref.replaceChildren(\`
  • \${input}
  • \`);" - } - ] -}" -`; - -exports[`javascript_lang_dangerous_insert_html insecure-property_assigment 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_dangerous_insert_html", - "title": "Unsanitized user input in dynamic HTML insertion (XSS)", - "description": "## Description\\nThere are XSS vulnerabilities when dynamically inserting HTML that contains unsanitized data.\\n\\n## Remediations\\nMake sure you use HTML sanitization library before inserting html\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html';\\n\\nconst html = \`\${user.Input}\`;\\ndocument.body.innerHTML = sanitizeHtml(html)\\n\`\`\`\\n\\n## Resources\\n- [OWASP XSS explained](https://owasp.org/www-community/attacks/xss/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_dangerous_insert_html", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure-property_assigment.js", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 2, - "end": 42 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 2, - "end": 42 - }, - "content": "this.ref.innerHTML = \`
  • \${input}
  • \`" - }, - "parent_line_number": 2, - "snippet": "this.ref.innerHTML = \`
  • \${input}
  • \`", - "fingerprint": "315770dda0d4ea464e59f5bd073bd950_0", - "old_fingerprint": "98894f5fc03e671c1269e70e059ae14f_0", - "code_extract": "\\tthis.ref.innerHTML = \`
  • \${input}
  • \`;" - } - ] -}" -`; - -exports[`javascript_lang_dangerous_insert_html secure 1`] = `"{}"`; diff --git a/tests/javascript/lang/dangerous_insert_html/test.js b/tests/javascript/lang/dangerous_insert_html/test.js index a7547f6b4..737af587e 100644 --- a/tests/javascript/lang/dangerous_insert_html/test.js +++ b/tests/javascript/lang/dangerous_insert_html/test.js @@ -1,31 +1,50 @@ -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("insecure-document_write", () => { + const testCase = "insecure-document_write.js" + + const results = invoke(testCase) - test("insecure-document_write", () => { - const testCase = "insecure-document_write.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("insecure-element_ref", () => { - const testCase = "insecure-element_ref.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure-element_ref", () => { + const testCase = "insecure-element_ref.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("insecure-property_assigment", () => { - const testCase = "insecure-property_assigment.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure-property_assigment", () => { + const testCase = "insecure-property_assigment.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/dangerous_insert_html/testdata/insecure-document_write.js b/tests/javascript/lang/dangerous_insert_html/testdata/insecure-document_write.js index f0c4b4a6e..0ac959533 100644 --- a/tests/javascript/lang/dangerous_insert_html/testdata/insecure-document_write.js +++ b/tests/javascript/lang/dangerous_insert_html/testdata/insecure-document_write.js @@ -1,18 +1,22 @@ function renderListItem(input) { +// bearer:expected javascript_lang_dangerous_insert_html document.write(`
  • ${input}
  • `) } const el = element.innerHTML function bad1(userInput) { +// bearer:expected javascript_lang_dangerous_insert_html el.innerHTML = "
    " + userInput + "
    " } function bad2(userInput) { +// bearer:expected javascript_lang_dangerous_insert_html document.body.outerHTML = userInput } function bad3(userInput) { const name = "
    " + userInput + "
    " +// bearer:expected javascript_lang_dangerous_insert_html document.write(name) } diff --git a/tests/javascript/lang/dangerous_insert_html/testdata/insecure-element_ref.js b/tests/javascript/lang/dangerous_insert_html/testdata/insecure-element_ref.js index 1c4d6c81b..d3c9545d4 100644 --- a/tests/javascript/lang/dangerous_insert_html/testdata/insecure-element_ref.js +++ b/tests/javascript/lang/dangerous_insert_html/testdata/insecure-element_ref.js @@ -1,3 +1,4 @@ function renderListItem(input) { +// bearer:expected javascript_lang_dangerous_insert_html this.ref.replaceChildren(`
  • ${input}
  • `); } diff --git a/tests/javascript/lang/dangerous_insert_html/testdata/insecure-property_assigment.js b/tests/javascript/lang/dangerous_insert_html/testdata/insecure-property_assigment.js index 6886f2723..60ad6fad1 100644 --- a/tests/javascript/lang/dangerous_insert_html/testdata/insecure-property_assigment.js +++ b/tests/javascript/lang/dangerous_insert_html/testdata/insecure-property_assigment.js @@ -1,3 +1,4 @@ function renderListItem(input) { +// bearer:expected javascript_lang_dangerous_insert_html this.ref.innerHTML = `
  • ${input}
  • `; } diff --git a/tests/javascript/lang/eval_user_input/__snapshots__/test.js.snap b/tests/javascript/lang/eval_user_input/__snapshots__/test.js.snap deleted file mode 100644 index dc193d55e..000000000 --- a/tests/javascript/lang/eval_user_input/__snapshots__/test.js.snap +++ /dev/null @@ -1,201 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_eval_user_input eval 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "95" - ], - "id": "javascript_lang_eval_user_input", - "title": "Unsanitized user input in 'eval' type function", - "description": "## Description\\nUsing \`eval\` (and similar code execution methods such as \`setTimeout\`) with user input is dangerous and can lead to remote code execution.\\n\\n## Remediation\\n❌ As a general rule, avoid using \`eval\`.\\n\\n❌ Avoid using code execution methods with unsanitized user input.\\n\\nInstead, it might be possible to use dynamic hardcoded values:\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n if req.params[\\"single_item\\"] {\\n myFunc = \\"(a) => a\\"\\n }\\n\\n setTimeout(myFunc);\\n };\\n\`\`\`\\nor pass user input to a compiled function, instead of compiling it with user input.\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n let compiledFunction = vm.compileFunction(myFunc);\\n compiledFunction(req.params[\\"pageCount\\"], req.params[\\"appendixPageCount\\"])\\n };\\n\`\`\`\\n\\n✅ Use JavaScript's strict mode as best practice and to minimize the reach of code execution methods\\n\\n\`\`\`javascript\\n \\"use strict\\"\\n\\n app.post(\\"/:id\\", (req, res) => {\\n ...\\n })\\n\`\`\`\\n\\n## Resources\\n- [MDN JavaScript strict mode reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_eval_user_input", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/eval.js", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 10, - "end": 23 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 10, - "end": 23 - }, - "content": "eval(command)" - }, - "parent_line_number": 12, - "snippet": "eval(command)", - "fingerprint": "845c467daab5771a9b5844e411f5576c_0", - "old_fingerprint": "047e7e7cf3819e02752e3eb5c918098c_0", - "code_extract": " return eval(command)" - }, - { - "cwe_ids": [ - "95" - ], - "id": "javascript_lang_eval_user_input", - "title": "Unsanitized user input in 'eval' type function", - "description": "## Description\\nUsing \`eval\` (and similar code execution methods such as \`setTimeout\`) with user input is dangerous and can lead to remote code execution.\\n\\n## Remediation\\n❌ As a general rule, avoid using \`eval\`.\\n\\n❌ Avoid using code execution methods with unsanitized user input.\\n\\nInstead, it might be possible to use dynamic hardcoded values:\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n if req.params[\\"single_item\\"] {\\n myFunc = \\"(a) => a\\"\\n }\\n\\n setTimeout(myFunc);\\n };\\n\`\`\`\\nor pass user input to a compiled function, instead of compiling it with user input.\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n let compiledFunction = vm.compileFunction(myFunc);\\n compiledFunction(req.params[\\"pageCount\\"], req.params[\\"appendixPageCount\\"])\\n };\\n\`\`\`\\n\\n✅ Use JavaScript's strict mode as best practice and to minimize the reach of code execution methods\\n\\n\`\`\`javascript\\n \\"use strict\\"\\n\\n app.post(\\"/:id\\", (req, res) => {\\n ...\\n })\\n\`\`\`\\n\\n## Resources\\n- [MDN JavaScript strict mode reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_eval_user_input", - "line_number": 20, - "full_filename": "/tmp/bearer-scan/eval.js", - "filename": ".", - "source": { - "start": 20, - "end": 20, - "column": { - "start": 3, - "end": 16 - } - }, - "sink": { - "start": 20, - "end": 20, - "column": { - "start": 3, - "end": 16 - }, - "content": "eval(context)" - }, - "parent_line_number": 20, - "snippet": "eval(context)", - "fingerprint": "845c467daab5771a9b5844e411f5576c_1", - "old_fingerprint": "047e7e7cf3819e02752e3eb5c918098c_1", - "code_extract": " eval(context)" - } - ] -}" -`; - -exports[`javascript_lang_eval_user_input new_function 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "95" - ], - "id": "javascript_lang_eval_user_input", - "title": "Unsanitized user input in 'eval' type function", - "description": "## Description\\nUsing \`eval\` (and similar code execution methods such as \`setTimeout\`) with user input is dangerous and can lead to remote code execution.\\n\\n## Remediation\\n❌ As a general rule, avoid using \`eval\`.\\n\\n❌ Avoid using code execution methods with unsanitized user input.\\n\\nInstead, it might be possible to use dynamic hardcoded values:\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n if req.params[\\"single_item\\"] {\\n myFunc = \\"(a) => a\\"\\n }\\n\\n setTimeout(myFunc);\\n };\\n\`\`\`\\nor pass user input to a compiled function, instead of compiling it with user input.\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n let compiledFunction = vm.compileFunction(myFunc);\\n compiledFunction(req.params[\\"pageCount\\"], req.params[\\"appendixPageCount\\"])\\n };\\n\`\`\`\\n\\n✅ Use JavaScript's strict mode as best practice and to minimize the reach of code execution methods\\n\\n\`\`\`javascript\\n \\"use strict\\"\\n\\n app.post(\\"/:id\\", (req, res) => {\\n ...\\n })\\n\`\`\`\\n\\n## Resources\\n- [MDN JavaScript strict mode reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_eval_user_input", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/new_function.js", - "filename": ".", - "source": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 24 - } - }, - "sink": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 24 - }, - "content": "new Function(command)" - }, - "parent_line_number": 11, - "snippet": "new Function(command)", - "fingerprint": "845c467daab5771a9b5844e411f5576c_0", - "old_fingerprint": "4751fd38350c5b49b6d4ff040230f0e4_0", - "code_extract": " new Function(command)()" - } - ] -}" -`; - -exports[`javascript_lang_eval_user_input secure 1`] = `"{}"`; - -exports[`javascript_lang_eval_user_input set_interval 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "95" - ], - "id": "javascript_lang_eval_user_input", - "title": "Unsanitized user input in 'eval' type function", - "description": "## Description\\nUsing \`eval\` (and similar code execution methods such as \`setTimeout\`) with user input is dangerous and can lead to remote code execution.\\n\\n## Remediation\\n❌ As a general rule, avoid using \`eval\`.\\n\\n❌ Avoid using code execution methods with unsanitized user input.\\n\\nInstead, it might be possible to use dynamic hardcoded values:\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n if req.params[\\"single_item\\"] {\\n myFunc = \\"(a) => a\\"\\n }\\n\\n setTimeout(myFunc);\\n };\\n\`\`\`\\nor pass user input to a compiled function, instead of compiling it with user input.\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n let compiledFunction = vm.compileFunction(myFunc);\\n compiledFunction(req.params[\\"pageCount\\"], req.params[\\"appendixPageCount\\"])\\n };\\n\`\`\`\\n\\n✅ Use JavaScript's strict mode as best practice and to minimize the reach of code execution methods\\n\\n\`\`\`javascript\\n \\"use strict\\"\\n\\n app.post(\\"/:id\\", (req, res) => {\\n ...\\n })\\n\`\`\`\\n\\n## Resources\\n- [MDN JavaScript strict mode reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_eval_user_input", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/set_interval.js", - "filename": ".", - "source": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 23 - } - }, - "sink": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 23 - }, - "content": "setInterval(command)" - }, - "parent_line_number": 11, - "snippet": "setInterval(command)", - "fingerprint": "845c467daab5771a9b5844e411f5576c_0", - "old_fingerprint": "bb4962f8468dfa6bd503cc5cbb72b698_0", - "code_extract": " setInterval(command)" - } - ] -}" -`; - -exports[`javascript_lang_eval_user_input set_timeout 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "95" - ], - "id": "javascript_lang_eval_user_input", - "title": "Unsanitized user input in 'eval' type function", - "description": "## Description\\nUsing \`eval\` (and similar code execution methods such as \`setTimeout\`) with user input is dangerous and can lead to remote code execution.\\n\\n## Remediation\\n❌ As a general rule, avoid using \`eval\`.\\n\\n❌ Avoid using code execution methods with unsanitized user input.\\n\\nInstead, it might be possible to use dynamic hardcoded values:\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n if req.params[\\"single_item\\"] {\\n myFunc = \\"(a) => a\\"\\n }\\n\\n setTimeout(myFunc);\\n };\\n\`\`\`\\nor pass user input to a compiled function, instead of compiling it with user input.\\n\`\`\`javascript\\n app.post(\\"/:id\\", (req, res) => {\\n let myFunc = \\"(a, b) => a + b\\"\\n let compiledFunction = vm.compileFunction(myFunc);\\n compiledFunction(req.params[\\"pageCount\\"], req.params[\\"appendixPageCount\\"])\\n };\\n\`\`\`\\n\\n✅ Use JavaScript's strict mode as best practice and to minimize the reach of code execution methods\\n\\n\`\`\`javascript\\n \\"use strict\\"\\n\\n app.post(\\"/:id\\", (req, res) => {\\n ...\\n })\\n\`\`\`\\n\\n## Resources\\n- [MDN JavaScript strict mode reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_eval_user_input", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/set_timeout.js", - "filename": ".", - "source": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 22 - } - }, - "sink": { - "start": 11, - "end": 11, - "column": { - "start": 3, - "end": 22 - }, - "content": "setTimeout(command)" - }, - "parent_line_number": 11, - "snippet": "setTimeout(command)", - "fingerprint": "845c467daab5771a9b5844e411f5576c_0", - "old_fingerprint": "166156db7e38b3833a5b23e795e25f54_0", - "code_extract": " setTimeout(command)" - } - ] -}" -`; diff --git a/tests/javascript/lang/eval_user_input/test.js b/tests/javascript/lang/eval_user_input/test.js index c48cee7ba..2ef4c5103 100644 --- a/tests/javascript/lang/eval_user_input/test.js +++ b/tests/javascript/lang/eval_user_input/test.js @@ -1,43 +1,60 @@ const { - createInvoker, createNewInvoker, getEnvironment, } = require("../../../helper.js") const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) describe(ruleId, () => { - const invoke = createInvoker(ruleId, ruleFile, testBase) - const newInvoke = createNewInvoker(ruleId, ruleFile, testBase) - - test("eval", () => { - const testCase = "eval.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("new-eval", () => { - const testCase = "eval.js" - const results = newInvoke(testCase) - expect(results.Missing).toEqual([]) - expect(results.Extra).toEqual([]) - }) - - test("new_function", () => { - const testCase = "new_function.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("set_interval", () => { - const testCase = "set_interval.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("set_timeout", () => { - const testCase = "set_timeout.js" - expect(invoke(testCase)).toMatchSnapshot() - }) -}) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + + test("eval", () => { + const testCase = "eval.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("new_function", () => { + const testCase = "new_function.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("set_interval", () => { + const testCase = "set_interval.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("set_timeout", () => { + const testCase = "set_timeout.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + +}) \ No newline at end of file diff --git a/tests/javascript/lang/eval_user_input/testdata/eval.js b/tests/javascript/lang/eval_user_input/testdata/eval.js index 4c6d6ed96..be98b82d2 100644 --- a/tests/javascript/lang/eval_user_input/testdata/eval.js +++ b/tests/javascript/lang/eval_user_input/testdata/eval.js @@ -9,6 +9,7 @@ app.post("/:id", (req, res) => { userInput = req.params.id var command = "new Function('" + userInput + "')" // bearer:expected javascript_lang_eval_user_input +// bearer:expected javascript_lang_eval_user_input return eval(command) }) @@ -17,5 +18,6 @@ const vm = require("node:vm") exports.handler = async function (event, _context) { const context = event["params"]["context"] // bearer:expected javascript_lang_eval_user_input +// bearer:expected javascript_lang_eval_user_input eval(context) } diff --git a/tests/javascript/lang/eval_user_input/testdata/new_function.js b/tests/javascript/lang/eval_user_input/testdata/new_function.js index b3ebfb629..24e5d2fc6 100644 --- a/tests/javascript/lang/eval_user_input/testdata/new_function.js +++ b/tests/javascript/lang/eval_user_input/testdata/new_function.js @@ -8,5 +8,6 @@ app.use(helmet.hidePoweredBy()) app.post("/:id", (req, res) => { userInput = req.params.id var command = "new Function('" + userInput + "')" +// bearer:expected javascript_lang_eval_user_input new Function(command)() }) diff --git a/tests/javascript/lang/eval_user_input/testdata/set_interval.js b/tests/javascript/lang/eval_user_input/testdata/set_interval.js index f222e6df6..df849b542 100644 --- a/tests/javascript/lang/eval_user_input/testdata/set_interval.js +++ b/tests/javascript/lang/eval_user_input/testdata/set_interval.js @@ -8,5 +8,6 @@ app.use(helmet.hidePoweredBy()) app.post("/:id", (req, res) => { userInput = req.params.id var command = "new Function('" + userInput + "')" +// bearer:expected javascript_lang_eval_user_input setInterval(command) }) diff --git a/tests/javascript/lang/eval_user_input/testdata/set_timeout.js b/tests/javascript/lang/eval_user_input/testdata/set_timeout.js index 007cc555a..7dc8d510d 100644 --- a/tests/javascript/lang/eval_user_input/testdata/set_timeout.js +++ b/tests/javascript/lang/eval_user_input/testdata/set_timeout.js @@ -8,6 +8,7 @@ app.use(helmet.hidePoweredBy()) app.post("/:id", (req, res) => { userInput = req.params.id var command = "new Function('" + userInput + "')" +// bearer:expected javascript_lang_eval_user_input setTimeout(command) var command2 = "new Function('" + (userInput ? ok : ok) + "')" diff --git a/tests/javascript/lang/exception/__snapshots__/test.js.snap b/tests/javascript/lang/exception/__snapshots__/test.js.snap deleted file mode 100644 index a5adfd502..000000000 --- a/tests/javascript/lang/exception/__snapshots__/test.js.snap +++ /dev/null @@ -1,239 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_exception promise_reject 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "210" - ], - "id": "javascript_lang_exception", - "title": "Leakage of sensitive data in exception message", - "description": "## Description\\n\\nLeaking sensitive data to an exception is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to exceptions.\\n\\n## Remediations\\n\\n❌ Avoid using sensitive data in exception messages:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, ensure to use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.uuid}\`)\\n\`\`\`\\n\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_exception", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/promise_reject.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 50, - "end": 60 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 5, - "end": 62 - }, - "content": "Promise.reject(new PermissionDenied(\\"fail\\" + user.email))" - }, - "parent_line_number": 5, - "snippet": "Promise.reject(new PermissionDenied(\\"fail\\" + user.email))", - "fingerprint": "bba6dc65c9d6db47ce50e7ab7f50f853_0", - "old_fingerprint": "da0026a5def4e4f489fa9b3008f96481_0", - "code_extract": " Promise.reject(new PermissionDenied(\\"fail\\" + user.email))" - } - ] -}" -`; - -exports[`javascript_lang_exception reject 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "210" - ], - "id": "javascript_lang_exception", - "title": "Leakage of sensitive data in exception message", - "description": "## Description\\n\\nLeaking sensitive data to an exception is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to exceptions.\\n\\n## Remediations\\n\\n❌ Avoid using sensitive data in exception messages:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, ensure to use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.uuid}\`)\\n\`\`\`\\n\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_exception", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/reject.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 9, - "end": 34 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 7, - "end": 40 - }, - "content": "reject(\\"Error with user \\" + user)" - }, - "parent_line_number": 7, - "snippet": "reject(\\"Error with user \\" + user)", - "fingerprint": "bba6dc65c9d6db47ce50e7ab7f50f853_0", - "old_fingerprint": "32fbb67159b1ad1c81f5b5bad0fbd9ff_0", - "code_extract": " reject(\\"Error with user \\" + user)" - }, - { - "cwe_ids": [ - "210" - ], - "id": "javascript_lang_exception", - "title": "Leakage of sensitive data in exception message", - "description": "## Description\\n\\nLeaking sensitive data to an exception is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to exceptions.\\n\\n## Remediations\\n\\n❌ Avoid using sensitive data in exception messages:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, ensure to use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.uuid}\`)\\n\`\`\`\\n\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_exception", - "line_number": 16, - "full_filename": "/tmp/bearer-scan/reject.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 14, - "end": 14, - "column": { - "start": 9, - "end": 34 - } - }, - "sink": { - "start": 16, - "end": 16, - "column": { - "start": 7, - "end": 40 - }, - "content": "reject(\\"Error with user \\" + user)" - }, - "parent_line_number": 16, - "snippet": "reject(\\"Error with user \\" + user)", - "fingerprint": "bba6dc65c9d6db47ce50e7ab7f50f853_1", - "old_fingerprint": "32fbb67159b1ad1c81f5b5bad0fbd9ff_1", - "code_extract": " reject(\\"Error with user \\" + user)" - } - ] -}" -`; - -exports[`javascript_lang_exception throw_custom_exception 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "210" - ], - "id": "javascript_lang_exception", - "title": "Leakage of sensitive data in exception message", - "description": "## Description\\n\\nLeaking sensitive data to an exception is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to exceptions.\\n\\n## Remediations\\n\\n❌ Avoid using sensitive data in exception messages:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, ensure to use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.uuid}\`)\\n\`\`\`\\n\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_exception", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/throw_custom_exception.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 46, - "end": 64 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 5, - "end": 67 - }, - "content": "throw new PermissionDenied(\`Error with \${current_user.email}\`)" - }, - "parent_line_number": 5, - "snippet": "throw new PermissionDenied(\`Error with \${current_user.email}\`)", - "fingerprint": "bba6dc65c9d6db47ce50e7ab7f50f853_0", - "old_fingerprint": "6e6b0780d0f087c941a439d0510874d7_0", - "code_extract": " throw new PermissionDenied(\`Error with \${current_user.email}\`)" - } - ] -}" -`; - -exports[`javascript_lang_exception throw_string 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "210" - ], - "id": "javascript_lang_exception", - "title": "Leakage of sensitive data in exception message", - "description": "## Description\\n\\nLeaking sensitive data to an exception is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to exceptions.\\n\\n## Remediations\\n\\n❌ Avoid using sensitive data in exception messages:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, ensure to use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nthrow new CustomError(\`Error with \${user.uuid}\`)\\n\`\`\`\\n\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_exception", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/throw_string.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 14, - "end": 24 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 5, - "end": 26 - }, - "content": "throw \`\${user.email}\`" - }, - "parent_line_number": 5, - "snippet": "throw \`\${user.email}\`", - "fingerprint": "bba6dc65c9d6db47ce50e7ab7f50f853_0", - "old_fingerprint": "95a519fc5dadded7300b3b7819ac09a8_0", - "code_extract": " throw \`\${user.email}\`" - } - ] -}" -`; diff --git a/tests/javascript/lang/exception/test.js b/tests/javascript/lang/exception/test.js index f506a17f1..a63d2a3ac 100644 --- a/tests/javascript/lang/exception/test.js +++ b/tests/javascript/lang/exception/test.js @@ -1,31 +1,50 @@ -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("promise_reject", () => { + const testCase = "promise_reject.js" + + const results = invoke(testCase) - test("promise_reject", () => { - const testCase = "promise_reject.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("reject", () => { - const testCase = "reject.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("reject", () => { + const testCase = "reject.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("throw_custom_exception", () => { - const testCase = "throw_custom_exception.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("throw_custom_exception", () => { + const testCase = "throw_custom_exception.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("throw_string", () => { - const testCase = "throw_string.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("throw_string", () => { + const testCase = "throw_string.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/exception/testdata/promise_reject.js b/tests/javascript/lang/exception/testdata/promise_reject.js index 494f468c7..f8395532a 100644 --- a/tests/javascript/lang/exception/testdata/promise_reject.js +++ b/tests/javascript/lang/exception/testdata/promise_reject.js @@ -2,6 +2,7 @@ return asyncIsPermitted().then(function (result) { if (result === true) { return true } else { +// bearer:expected javascript_lang_exception Promise.reject(new PermissionDenied("fail" + user.email)) } }) diff --git a/tests/javascript/lang/exception/testdata/reject.js b/tests/javascript/lang/exception/testdata/reject.js index d16edd572..038a066ab 100644 --- a/tests/javascript/lang/exception/testdata/reject.js +++ b/tests/javascript/lang/exception/testdata/reject.js @@ -4,6 +4,7 @@ function main() { const user = { email: current_user.email, } +// bearer:expected javascript_lang_exception reject("Error with user " + user) }, 2000) }) @@ -13,6 +14,7 @@ function main() { const user = { email: current_user.email, } +// bearer:expected javascript_lang_exception reject("Error with user " + user) }, 2000) }) diff --git a/tests/javascript/lang/exception/testdata/throw_custom_exception.js b/tests/javascript/lang/exception/testdata/throw_custom_exception.js index f6f5f579b..706a8e625 100644 --- a/tests/javascript/lang/exception/testdata/throw_custom_exception.js +++ b/tests/javascript/lang/exception/testdata/throw_custom_exception.js @@ -2,6 +2,7 @@ return asyncIsPermitted().then(function (result) { if (result === true) { return true } else { +// bearer:expected javascript_lang_exception throw new PermissionDenied(`Error with ${current_user.email}`) } }) diff --git a/tests/javascript/lang/exception/testdata/throw_string.js b/tests/javascript/lang/exception/testdata/throw_string.js index e012532e1..ac567fc8e 100644 --- a/tests/javascript/lang/exception/testdata/throw_string.js +++ b/tests/javascript/lang/exception/testdata/throw_string.js @@ -2,6 +2,7 @@ return asyncIsPermitted().then(function (result) { if (result === true) { throw `${user.email ? ok : ok}` } else { +// bearer:expected javascript_lang_exception throw `${user.email}` } }) diff --git a/tests/javascript/lang/file_generation/__snapshots__/test.js.snap b/tests/javascript/lang/file_generation/__snapshots__/test.js.snap deleted file mode 100644 index 04d67ee32..000000000 --- a/tests/javascript/lang/file_generation/__snapshots__/test.js.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_file_generation file_generation 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "313" - ], - "id": "javascript_lang_file_generation", - "title": "Leakage of sensitive data in dynamic file generation", - "description": "## Description\\n\\nIt is not uncommon to generate logs, backups, or data exports to static file formats. This rule checks if code exists to write sensitive data to static files.\\n\\n## Remediations\\n\\nAvoid writing sensitive data to logs, backups, or exports whenever possible. Instead obfuscate and/or filter the data to exclude sensitive information.\\n\\n\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_file_generation", - "line_number": 15, - "full_filename": "/tmp/bearer-scan/file_generation.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Firstname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 10, - "end": 10, - "column": { - "start": 15, - "end": 29 - } - }, - "sink": { - "start": 15, - "end": 18, - "column": { - "start": 1, - "end": 3 - }, - "content": "fs.writeFile(\\"data.csv\\", JSON.stringify(users), \\"utf-8\\", (err) => {\\n if (err) console.log(err)\\n else console.log(\\"Data saved\\")\\n})" - }, - "parent_line_number": 15, - "snippet": "fs.writeFile(\\"data.csv\\", JSON.stringify(users), \\"utf-8\\", (err) => {\\n if (err) console.log(err)\\n else console.log(\\"Data saved\\")\\n})", - "fingerprint": "7162a96ee591e4689c1fa24bfcc02fd5_0", - "old_fingerprint": "e07392ef7687a29685f9b9f7fd673469_0", - "code_extract": "fs.writeFile(\\"data.csv\\", JSON.stringify(users), \\"utf-8\\", (err) => {\\n if (err) console.log(err)\\n else console.log(\\"Data saved\\")\\n})" - } - ] -}" -`; diff --git a/tests/javascript/lang/file_generation/test.js b/tests/javascript/lang/file_generation/test.js index 50a736fa6..04ebe2e52 100644 --- a/tests/javascript/lang/file_generation/test.js +++ b/tests/javascript/lang/file_generation/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("file_generation", () => { + const testCase = "file_generation.js" + + const results = invoke(testCase) - test("file_generation", () => { - const testCase = "file_generation.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/file_generation/testdata/file_generation.js b/tests/javascript/lang/file_generation/testdata/file_generation.js index 77c609c0a..bb92c0709 100644 --- a/tests/javascript/lang/file_generation/testdata/file_generation.js +++ b/tests/javascript/lang/file_generation/testdata/file_generation.js @@ -12,6 +12,7 @@ const users = [{ }] fs.writeFile("data.csv", JSON.stringify(users), callback) +// bearer:expected javascript_lang_file_generation fs.writeFile("data.csv", JSON.stringify(users), "utf-8", (err) => { if (err) console.log(err) else console.log("Data saved") diff --git a/tests/javascript/lang/format_string_using_user_input/__snapshots__/test.js.snap b/tests/javascript/lang/format_string_using_user_input/__snapshots__/test.js.snap deleted file mode 100644 index 945e7db76..000000000 --- a/tests/javascript/lang/format_string_using_user_input/__snapshots__/test.js.snap +++ /dev/null @@ -1,112 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_format_string_using_user_input bad 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "134" - ], - "id": "javascript_lang_format_string_using_user_input", - "title": "Unsanitized user input in format string", - "description": "## Description\\n\\nIf an application includes user input directly in a format string, an\\nattacker can use format specifiers in the user input to produce misleading\\nor fabricated messages.\\n\\n## Remediations\\n\\n❌ Avoid format strings containing user input:\\n\\n\`\`\`javascript\\nconsole.log(\`The value was \${req.params.value}\`)\\n\`\`\`\\n\\n✅ Use a literal format string with additional arguments:\\n\\n\`\`\`javascript\\nconsole.log(\\"The value was %s\\", req.params.value)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_format_string_using_user_input", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 47 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 47 - }, - "content": "console.error(\`Value: \${req.params.value}\`, e)" - }, - "parent_line_number": 1, - "snippet": "console.error(\`Value: \${req.params.value}\`, e)", - "fingerprint": "16cab48ad098a8cc47c366d7cec8f691_0", - "old_fingerprint": "2c779a0497da541764199928f8f852c2_0", - "code_extract": "console.error(\`Value: \${req.params.value}\`, e)" - }, - { - "cwe_ids": [ - "134" - ], - "id": "javascript_lang_format_string_using_user_input", - "title": "Unsanitized user input in format string", - "description": "## Description\\n\\nIf an application includes user input directly in a format string, an\\nattacker can use format specifiers in the user input to produce misleading\\nor fabricated messages.\\n\\n## Remediations\\n\\n❌ Avoid format strings containing user input:\\n\\n\`\`\`javascript\\nconsole.log(\`The value was \${req.params.value}\`)\\n\`\`\`\\n\\n✅ Use a literal format string with additional arguments:\\n\\n\`\`\`javascript\\nconsole.log(\\"The value was %s\\", req.params.value)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_format_string_using_user_input", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 42 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 42 - }, - "content": "util.format(\`Value: \${req.params.value}\`)" - }, - "parent_line_number": 3, - "snippet": "util.format(\`Value: \${req.params.value}\`)", - "fingerprint": "16cab48ad098a8cc47c366d7cec8f691_1", - "old_fingerprint": "2c779a0497da541764199928f8f852c2_1", - "code_extract": "util.format(\`Value: \${req.params.value}\`)" - }, - { - "cwe_ids": [ - "134" - ], - "id": "javascript_lang_format_string_using_user_input", - "title": "Unsanitized user input in format string", - "description": "## Description\\n\\nIf an application includes user input directly in a format string, an\\nattacker can use format specifiers in the user input to produce misleading\\nor fabricated messages.\\n\\n## Remediations\\n\\n❌ Avoid format strings containing user input:\\n\\n\`\`\`javascript\\nconsole.log(\`The value was \${req.params.value}\`)\\n\`\`\`\\n\\n✅ Use a literal format string with additional arguments:\\n\\n\`\`\`javascript\\nconsole.log(\\"The value was %s\\", req.params.value)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_format_string_using_user_input", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 63 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 63 - }, - "content": "util.formatWithOptions({}, \`Value: \${req.params.value} %s\`, x)" - }, - "parent_line_number": 5, - "snippet": "util.formatWithOptions({}, \`Value: \${req.params.value} %s\`, x)", - "fingerprint": "16cab48ad098a8cc47c366d7cec8f691_2", - "old_fingerprint": "2c779a0497da541764199928f8f852c2_2", - "code_extract": "util.formatWithOptions({}, \`Value: \${req.params.value} %s\`, x)" - } - ] -}" -`; - -exports[`javascript_lang_format_string_using_user_input ok 1`] = `"{}"`; diff --git a/tests/javascript/lang/format_string_using_user_input/test.js b/tests/javascript/lang/format_string_using_user_input/test.js index fa284d13a..fc42999a0 100644 --- a/tests/javascript/lang/format_string_using_user_input/test.js +++ b/tests/javascript/lang/format_string_using_user_input/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.js" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/format_string_using_user_input/testdata/bad.js b/tests/javascript/lang/format_string_using_user_input/testdata/bad.js index 564167e11..c9e9ed77d 100644 --- a/tests/javascript/lang/format_string_using_user_input/testdata/bad.js +++ b/tests/javascript/lang/format_string_using_user_input/testdata/bad.js @@ -1,5 +1,8 @@ +// bearer:expected javascript_lang_format_string_using_user_input console.error(`Value: ${req.params.value}`, e) +// bearer:expected javascript_lang_format_string_using_user_input util.format(`Value: ${req.params.value}`) +// bearer:expected javascript_lang_format_string_using_user_input util.formatWithOptions({}, `Value: ${req.params.value} %s`, x) diff --git a/tests/javascript/lang/hardcoded_secret/__snapshots__/test.js.snap b/tests/javascript/lang/hardcoded_secret/__snapshots__/test.js.snap deleted file mode 100644 index 97bc9cecf..000000000 --- a/tests/javascript/lang/hardcoded_secret/__snapshots__/test.js.snap +++ /dev/null @@ -1,334 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_hardcoded_secret insecure_assigment 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: 'my-id-123',\\n clientSecret: 'shh-my-secret',\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: process.env.CLIENT_ID,\\n clientSecret: process.env.CLIENT_SECRET,\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption, to manage and access your secrets\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_hardcoded_secret", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure_assigment.js", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 1, - "end": 46 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 1, - "end": 46 - }, - "content": "config.clientSecret = \\"secretHardcodedString\\"" - }, - "parent_line_number": 2, - "snippet": "config.clientSecret = \\"secretHardcodedString\\"", - "fingerprint": "68ec549b0c4baac7ca684eb14e42834e_0", - "old_fingerprint": "cb0768aaec39cd633bcc91bca96ca617_0", - "code_extract": "config.clientSecret = \\"secretHardcodedString\\";" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: 'my-id-123',\\n clientSecret: 'shh-my-secret',\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: process.env.CLIENT_ID,\\n clientSecret: process.env.CLIENT_SECRET,\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption, to manage and access your secrets\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_hardcoded_secret", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/insecure_assigment.js", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 22 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 22 - }, - "content": "const apiKey = \\"oops\\"" - }, - "parent_line_number": 4, - "snippet": "const apiKey = \\"oops\\"", - "fingerprint": "68ec549b0c4baac7ca684eb14e42834e_1", - "old_fingerprint": "cb0768aaec39cd633bcc91bca96ca617_1", - "code_extract": "const apiKey = \\"oops\\"" - } - ] -}" -`; - -exports[`javascript_lang_hardcoded_secret insecure_crypto 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: 'my-id-123',\\n clientSecret: 'shh-my-secret',\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: process.env.CLIENT_ID,\\n clientSecret: process.env.CLIENT_SECRET,\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption, to manage and access your secrets\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_hardcoded_secret", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/insecure_crypto.js", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 76 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 76 - }, - "content": "crypto.createHmac('sha256', 'secretHardcodedString', { encoding: \\"utf-8\\" })" - }, - "parent_line_number": 1, - "snippet": "crypto.createHmac('sha256', 'secretHardcodedString', { encoding: \\"utf-8\\" })", - "fingerprint": "68ec549b0c4baac7ca684eb14e42834e_0", - "old_fingerprint": "57fd1461af37edfce7e2eb6fa55b50d3_0", - "code_extract": "crypto.createHmac('sha256', 'secretHardcodedString', { encoding: \\"utf-8\\" })" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: 'my-id-123',\\n clientSecret: 'shh-my-secret',\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: process.env.CLIENT_ID,\\n clientSecret: process.env.CLIENT_SECRET,\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption, to manage and access your secrets\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_hardcoded_secret", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/insecure_crypto.js", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 57 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 57 - }, - "content": "crypto.createSecretKey('secretHardcodedString', \\"utf-8\\")" - }, - "parent_line_number": 3, - "snippet": "crypto.createSecretKey('secretHardcodedString', \\"utf-8\\")", - "fingerprint": "68ec549b0c4baac7ca684eb14e42834e_1", - "old_fingerprint": "57fd1461af37edfce7e2eb6fa55b50d3_1", - "code_extract": "crypto.createSecretKey('secretHardcodedString', \\"utf-8\\")" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: 'my-id-123',\\n clientSecret: 'shh-my-secret',\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: process.env.CLIENT_ID,\\n clientSecret: process.env.CLIENT_SECRET,\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption, to manage and access your secrets\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_hardcoded_secret", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/insecure_crypto.js", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 49 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 49 - }, - "content": "crypto.createPrivateKey('secretHardcodedString')" - }, - "parent_line_number": 5, - "snippet": "crypto.createPrivateKey('secretHardcodedString')", - "fingerprint": "68ec549b0c4baac7ca684eb14e42834e_2", - "old_fingerprint": "57fd1461af37edfce7e2eb6fa55b50d3_2", - "code_extract": "crypto.createPrivateKey('secretHardcodedString')" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: 'my-id-123',\\n clientSecret: 'shh-my-secret',\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: process.env.CLIENT_ID,\\n clientSecret: process.env.CLIENT_SECRET,\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption, to manage and access your secrets\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_hardcoded_secret", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/insecure_crypto.js", - "filename": ".", - "source": { - "start": 7, - "end": 7, - "column": { - "start": 1, - "end": 64 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 1, - "end": 64 - }, - "content": "crypto.privateDecrypt({ key: 'secretHardcodedString' }, buffer)" - }, - "parent_line_number": 7, - "snippet": "crypto.privateDecrypt({ key: 'secretHardcodedString' }, buffer)", - "fingerprint": "68ec549b0c4baac7ca684eb14e42834e_3", - "old_fingerprint": "57fd1461af37edfce7e2eb6fa55b50d3_3", - "code_extract": "crypto.privateDecrypt({ key: 'secretHardcodedString' }, buffer)" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: 'my-id-123',\\n clientSecret: 'shh-my-secret',\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: process.env.CLIENT_ID,\\n clientSecret: process.env.CLIENT_SECRET,\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption, to manage and access your secrets\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_hardcoded_secret", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/insecure_crypto.js", - "filename": ".", - "source": { - "start": 9, - "end": 9, - "column": { - "start": 1, - "end": 71 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 1, - "end": 71 - }, - "content": "crypto.privateEncrypt({ passphrase: 'secretHardcodedString' }, buffer)" - }, - "parent_line_number": 9, - "snippet": "crypto.privateEncrypt({ passphrase: 'secretHardcodedString' }, buffer)", - "fingerprint": "68ec549b0c4baac7ca684eb14e42834e_4", - "old_fingerprint": "57fd1461af37edfce7e2eb6fa55b50d3_4", - "code_extract": "crypto.privateEncrypt({ passphrase: 'secretHardcodedString' }, buffer)" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: 'my-id-123',\\n clientSecret: 'shh-my-secret',\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: process.env.CLIENT_ID,\\n clientSecret: process.env.CLIENT_SECRET,\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption, to manage and access your secrets\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_hardcoded_secret", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/insecure_crypto.js", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 1, - "end": 41 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 1, - "end": 41 - }, - "content": "s.sign('secretHardcodedString', \\"utf-8\\")" - }, - "parent_line_number": 12, - "snippet": "s.sign('secretHardcodedString', \\"utf-8\\")", - "fingerprint": "68ec549b0c4baac7ca684eb14e42834e_5", - "old_fingerprint": "57fd1461af37edfce7e2eb6fa55b50d3_5", - "code_extract": "s.sign('secretHardcodedString', \\"utf-8\\")" - } - ] -}" -`; - -exports[`javascript_lang_hardcoded_secret insecure_object 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_hardcoded_secret", - "title": "Usage of hard-coded secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets. Use environment variables or a secret management system instead.\\n\\n## Remediations\\n\\n❌ Do not store plaintext secrets in your code\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: 'my-id-123',\\n clientSecret: 'shh-my-secret',\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use environment variables\\n\\n\`\`\`javascript\\n passport.use(new OAuth2Strategy({\\n authorizationURL: 'https://www.example.com/oauth2/authorize',\\n tokenURL: 'https://www.example.com/oauth2/token',\\n clientID: process.env.CLIENT_ID,\\n clientSecret: process.env.CLIENT_SECRET,\\n callbackURL: 'http://localhost:3000/auth/example/callback'\\n },\\n function(accessToken, refreshToken, profile, cb) {\\n User.findOrCreate({ exampleId: profile.id }, function (err, user) {\\n return cb(err, user);\\n });\\n }\\n ));\\n\`\`\`\\n\\n✅ Use a secret management system or even better, a key management service (KMS) with encryption, to manage and access your secrets\\n\\n## Resources\\n- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)\\n- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs)\\n- [AWS Key Management Service](https://aws.amazon.com/kms/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_hardcoded_secret", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/insecure_object.js", - "filename": ".", - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 2, - "end": 39 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 2, - "end": 39 - }, - "content": "clientSecret: \\"secretHardcodedString\\"" - }, - "parent_line_number": 3, - "snippet": "clientSecret: \\"secretHardcodedString\\"", - "fingerprint": "68ec549b0c4baac7ca684eb14e42834e_0", - "old_fingerprint": "96d420b4e549b4b59b1846d59c40595a_0", - "code_extract": "\\tclientSecret: \\"secretHardcodedString\\"," - } - ] -}" -`; - -exports[`javascript_lang_hardcoded_secret secure 1`] = `"{}"`; diff --git a/tests/javascript/lang/hardcoded_secret/test.js b/tests/javascript/lang/hardcoded_secret/test.js index bbcee4836..03007c614 100644 --- a/tests/javascript/lang/hardcoded_secret/test.js +++ b/tests/javascript/lang/hardcoded_secret/test.js @@ -1,31 +1,50 @@ -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("insecure_assigment", () => { + const testCase = "insecure_assigment.js" + + const results = invoke(testCase) - test("insecure_assigment", () => { - const testCase = "insecure_assigment.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("insecure_crypto", () => { - const testCase = "insecure_crypto.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure_crypto", () => { + const testCase = "insecure_crypto.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("insecure_object", () => { - const testCase = "insecure_object.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure_object", () => { + const testCase = "insecure_object.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/hardcoded_secret/testdata/insecure_assigment.js b/tests/javascript/lang/hardcoded_secret/testdata/insecure_assigment.js index e4721cedb..061e317c8 100644 --- a/tests/javascript/lang/hardcoded_secret/testdata/insecure_assigment.js +++ b/tests/javascript/lang/hardcoded_secret/testdata/insecure_assigment.js @@ -1,4 +1,6 @@ const config = {}; +// bearer:expected javascript_lang_hardcoded_secret config.clientSecret = "secretHardcodedString"; +// bearer:expected javascript_lang_hardcoded_secret const apiKey = "oops" diff --git a/tests/javascript/lang/hardcoded_secret/testdata/insecure_crypto.js b/tests/javascript/lang/hardcoded_secret/testdata/insecure_crypto.js index 238509af0..7dffb351b 100644 --- a/tests/javascript/lang/hardcoded_secret/testdata/insecure_crypto.js +++ b/tests/javascript/lang/hardcoded_secret/testdata/insecure_crypto.js @@ -1,12 +1,18 @@ +// bearer:expected javascript_lang_hardcoded_secret crypto.createHmac('sha256', 'secretHardcodedString', { encoding: "utf-8" }) +// bearer:expected javascript_lang_hardcoded_secret crypto.createSecretKey('secretHardcodedString', "utf-8") +// bearer:expected javascript_lang_hardcoded_secret crypto.createPrivateKey('secretHardcodedString') +// bearer:expected javascript_lang_hardcoded_secret crypto.privateDecrypt({ key: 'secretHardcodedString' }, buffer) +// bearer:expected javascript_lang_hardcoded_secret crypto.privateEncrypt({ passphrase: 'secretHardcodedString' }, buffer) const s = crypto.createSign('RSA-SHA256') +// bearer:expected javascript_lang_hardcoded_secret s.sign('secretHardcodedString', "utf-8") diff --git a/tests/javascript/lang/hardcoded_secret/testdata/insecure_object.js b/tests/javascript/lang/hardcoded_secret/testdata/insecure_object.js index 20b2641db..9a39fd99a 100644 --- a/tests/javascript/lang/hardcoded_secret/testdata/insecure_object.js +++ b/tests/javascript/lang/hardcoded_secret/testdata/insecure_object.js @@ -1,5 +1,6 @@ const config = { clientID: process.env["GOOGLE_CLIENT_ID"], +// bearer:expected javascript_lang_hardcoded_secret clientSecret: "secretHardcodedString", callbackURL: "/oauth2/redirect/google", scope: ["profile"], diff --git a/tests/javascript/lang/http_insecure/__snapshots__/test.js.snap b/tests/javascript/lang/http_insecure/__snapshots__/test.js.snap deleted file mode 100644 index eae959ed1..000000000 --- a/tests/javascript/lang/http_insecure/__snapshots__/test.js.snap +++ /dev/null @@ -1,214 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_http_insecure axios_insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "319" - ], - "id": "javascript_lang_http_insecure", - "title": "Usage of insecure HTTP connection", - "description": "## Description\\n\\nApplications should only connect to API using HTTPS connections. This rule checks that all HTTP connections use HTTPS.\\n\\n❌ Avoid using unsecured outgoing HTTP communication, especially in the context of API calls:\\n\\n\`\`\`javascript\\nconst response = axios.get('http://insecure-api.com')\\n\`\`\`\\n\\n✅ Ensure to always connect though HTTPS:\\n\\n\`\`\`javascript\\nconst response = axios.get('https://secure-api.com')\\n\`\`\`\\n\\n## Resources\\n- [OWASP insecure transport](https://owasp.org/www-community/vulnerabilities/Insecure_Transport)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_insecure", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/axios_insecure.js", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 1, - "end": 24 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 1, - "end": 24 - }, - "content": "axios.get(insecure_url)" - }, - "parent_line_number": 2, - "snippet": "axios.get(insecure_url)", - "fingerprint": "152209b1605ebd60ec2a741fa69edfbe_0", - "old_fingerprint": "1f10f9d4145ab9e1ffd7e07066362fc9_0", - "code_extract": "axios.get(insecure_url);" - } - ] -}" -`; - -exports[`javascript_lang_http_insecure axios_secure 1`] = `"{}"`; - -exports[`javascript_lang_http_insecure axios_with_config_insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "319" - ], - "id": "javascript_lang_http_insecure", - "title": "Usage of insecure HTTP connection", - "description": "## Description\\n\\nApplications should only connect to API using HTTPS connections. This rule checks that all HTTP connections use HTTPS.\\n\\n❌ Avoid using unsecured outgoing HTTP communication, especially in the context of API calls:\\n\\n\`\`\`javascript\\nconst response = axios.get('http://insecure-api.com')\\n\`\`\`\\n\\n✅ Ensure to always connect though HTTPS:\\n\\n\`\`\`javascript\\nconst response = axios.get('https://secure-api.com')\\n\`\`\`\\n\\n## Resources\\n- [OWASP insecure transport](https://owasp.org/www-community/vulnerabilities/Insecure_Transport)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_insecure", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/axios_with_config_insecure.js", - "filename": ".", - "source": { - "start": 7, - "end": 7, - "column": { - "start": 1, - "end": 14 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 1, - "end": 14 - }, - "content": "axios(config)" - }, - "parent_line_number": 7, - "snippet": "axios(config)", - "fingerprint": "152209b1605ebd60ec2a741fa69edfbe_0", - "old_fingerprint": "b8b4eeebd04a512d167c3f2dd39fa556_0", - "code_extract": "axios(config);" - } - ] -}" -`; - -exports[`javascript_lang_http_insecure fetch_insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "319" - ], - "id": "javascript_lang_http_insecure", - "title": "Usage of insecure HTTP connection", - "description": "## Description\\n\\nApplications should only connect to API using HTTPS connections. This rule checks that all HTTP connections use HTTPS.\\n\\n❌ Avoid using unsecured outgoing HTTP communication, especially in the context of API calls:\\n\\n\`\`\`javascript\\nconst response = axios.get('http://insecure-api.com')\\n\`\`\`\\n\\n✅ Ensure to always connect though HTTPS:\\n\\n\`\`\`javascript\\nconst response = axios.get('https://secure-api.com')\\n\`\`\`\\n\\n## Resources\\n- [OWASP insecure transport](https://owasp.org/www-community/vulnerabilities/Insecure_Transport)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_insecure", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/fetch_insecure.js", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 20 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 20 - }, - "content": "fetch(insecure_url)" - }, - "parent_line_number": 3, - "snippet": "fetch(insecure_url)", - "fingerprint": "152209b1605ebd60ec2a741fa69edfbe_0", - "old_fingerprint": "9ba0534036506895e88efb0eea617717_0", - "code_extract": "fetch(insecure_url)" - } - ] -}" -`; - -exports[`javascript_lang_http_insecure fetch_secure 1`] = `"{}"`; - -exports[`javascript_lang_http_insecure request_insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "319" - ], - "id": "javascript_lang_http_insecure", - "title": "Usage of insecure HTTP connection", - "description": "## Description\\n\\nApplications should only connect to API using HTTPS connections. This rule checks that all HTTP connections use HTTPS.\\n\\n❌ Avoid using unsecured outgoing HTTP communication, especially in the context of API calls:\\n\\n\`\`\`javascript\\nconst response = axios.get('http://insecure-api.com')\\n\`\`\`\\n\\n✅ Ensure to always connect though HTTPS:\\n\\n\`\`\`javascript\\nconst response = axios.get('https://secure-api.com')\\n\`\`\`\\n\\n## Resources\\n- [OWASP insecure transport](https://owasp.org/www-community/vulnerabilities/Insecure_Transport)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_insecure", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/request_insecure.js", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 38 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 38 - }, - "content": "request(insecure_url, function () {})" - }, - "parent_line_number": 3, - "snippet": "request(insecure_url, function () {})", - "fingerprint": "152209b1605ebd60ec2a741fa69edfbe_0", - "old_fingerprint": "c11ee76b3bb4d2ecda30c97c577c8f16_0", - "code_extract": "request(insecure_url, function () {});" - } - ] -}" -`; - -exports[`javascript_lang_http_insecure request_secure 1`] = `"{}"`; - -exports[`javascript_lang_http_insecure xmlhttp_insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "319" - ], - "id": "javascript_lang_http_insecure", - "title": "Usage of insecure HTTP connection", - "description": "## Description\\n\\nApplications should only connect to API using HTTPS connections. This rule checks that all HTTP connections use HTTPS.\\n\\n❌ Avoid using unsecured outgoing HTTP communication, especially in the context of API calls:\\n\\n\`\`\`javascript\\nconst response = axios.get('http://insecure-api.com')\\n\`\`\`\\n\\n✅ Ensure to always connect though HTTPS:\\n\\n\`\`\`javascript\\nconst response = axios.get('https://secure-api.com')\\n\`\`\`\\n\\n## Resources\\n- [OWASP insecure transport](https://owasp.org/www-community/vulnerabilities/Insecure_Transport)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_insecure", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/xmlhttp_insecure.js", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 38 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 38 - }, - "content": "xhttp.open(\\"GET\\", insecure_url, true)" - }, - "parent_line_number": 5, - "snippet": "xhttp.open(\\"GET\\", insecure_url, true)", - "fingerprint": "152209b1605ebd60ec2a741fa69edfbe_0", - "old_fingerprint": "03147e05ae4e41b8a8bad86a66ad2fe7_0", - "code_extract": "xhttp.open(\\"GET\\", insecure_url, true);" - } - ] -}" -`; - -exports[`javascript_lang_http_insecure xmlhttp_secure 1`] = `"{}"`; diff --git a/tests/javascript/lang/http_insecure/test.js b/tests/javascript/lang/http_insecure/test.js index fbc97b6bd..ce083c25f 100644 --- a/tests/javascript/lang/http_insecure/test.js +++ b/tests/javascript/lang/http_insecure/test.js @@ -1,61 +1,100 @@ -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("axios_insecure", () => { + const testCase = "axios_insecure.js" + + const results = invoke(testCase) - test("axios_insecure", () => { - const testCase = "axios_insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("axios_secure", () => { - const testCase = "axios_secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("axios_secure", () => { + const testCase = "axios_secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("axios_with_config_insecure", () => { - const testCase = "axios_with_config_insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("axios_with_config_insecure", () => { + const testCase = "axios_with_config_insecure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("fetch_insecure", () => { - const testCase = "fetch_insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("fetch_insecure", () => { + const testCase = "fetch_insecure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("fetch_secure", () => { - const testCase = "fetch_secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("fetch_secure", () => { + const testCase = "fetch_secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("request_insecure", () => { - const testCase = "request_insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("request_insecure", () => { + const testCase = "request_insecure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("request_secure", () => { - const testCase = "request_secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("request_secure", () => { + const testCase = "request_secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("xmlhttp_insecure", () => { - const testCase = "xmlhttp_insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("xmlhttp_insecure", () => { + const testCase = "xmlhttp_insecure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("xmlhttp_secure", () => { - const testCase = "xmlhttp_secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("xmlhttp_secure", () => { + const testCase = "xmlhttp_secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/http_insecure/testdata/axios_insecure.js b/tests/javascript/lang/http_insecure/testdata/axios_insecure.js index 6b182ed97..ded83f574 100644 --- a/tests/javascript/lang/http_insecure/testdata/axios_insecure.js +++ b/tests/javascript/lang/http_insecure/testdata/axios_insecure.js @@ -1,2 +1,3 @@ const insecure_url = "http://domain.com/api/movies"; +// bearer:expected javascript_lang_http_insecure axios.get(insecure_url); diff --git a/tests/javascript/lang/http_insecure/testdata/axios_with_config_insecure.js b/tests/javascript/lang/http_insecure/testdata/axios_with_config_insecure.js index f95e15f99..02c6eeb33 100644 --- a/tests/javascript/lang/http_insecure/testdata/axios_with_config_insecure.js +++ b/tests/javascript/lang/http_insecure/testdata/axios_with_config_insecure.js @@ -4,4 +4,5 @@ const config = { headers: { "content-type": "application/json" }, url: insecure_url, }; +// bearer:expected javascript_lang_http_insecure axios(config); diff --git a/tests/javascript/lang/http_insecure/testdata/fetch_insecure.js b/tests/javascript/lang/http_insecure/testdata/fetch_insecure.js index 96bd5cc8a..e105d28fe 100644 --- a/tests/javascript/lang/http_insecure/testdata/fetch_insecure.js +++ b/tests/javascript/lang/http_insecure/testdata/fetch_insecure.js @@ -1,5 +1,6 @@ const insecure_url = "http://example.com/movies.json"; +// bearer:expected javascript_lang_http_insecure fetch(insecure_url) .then((response) => response.json()) .then((data) => console.log(data)); diff --git a/tests/javascript/lang/http_insecure/testdata/request_insecure.js b/tests/javascript/lang/http_insecure/testdata/request_insecure.js index 7179c7e16..196332a1c 100644 --- a/tests/javascript/lang/http_insecure/testdata/request_insecure.js +++ b/tests/javascript/lang/http_insecure/testdata/request_insecure.js @@ -1,3 +1,4 @@ var insecure_url = "http://domain.com/movie"; +// bearer:expected javascript_lang_http_insecure request(insecure_url, function () {}); diff --git a/tests/javascript/lang/http_insecure/testdata/xmlhttp_insecure.js b/tests/javascript/lang/http_insecure/testdata/xmlhttp_insecure.js index 8cfdef9b4..f989b4f60 100644 --- a/tests/javascript/lang/http_insecure/testdata/xmlhttp_insecure.js +++ b/tests/javascript/lang/http_insecure/testdata/xmlhttp_insecure.js @@ -2,4 +2,5 @@ var xhttp = new XMLHttpRequest(); var insecure_url = "http://domain.com/movie"; +// bearer:expected javascript_lang_http_insecure xhttp.open("GET", insecure_url, true); diff --git a/tests/javascript/lang/http_url_using_user_input/__snapshots__/test.js.snap b/tests/javascript/lang/http_url_using_user_input/__snapshots__/test.js.snap deleted file mode 100644 index 9313efd89..000000000 --- a/tests/javascript/lang/http_url_using_user_input/__snapshots__/test.js.snap +++ /dev/null @@ -1,282 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_http_url_using_user_input bad 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "918" - ], - "id": "javascript_lang_http_url_using_user_input", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\n\\nApplications should not connect to locations formed from user input.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in HTTP URLs:\\n\\n\`\`\`javascript\\nconst response = axios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nconst hosts = new Map([\\n [\\"option1\\", \\"api1.com\\"],\\n [\\"option2\\", \\"api2.com\\"]\\n])\\n\\nconst host = hosts.get(req.params.host)\\nconst response = axois.get(\`https://\${host}\`)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_url_using_user_input", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 6, - "end": 6, - "column": { - "start": 1, - "end": 20 - } - }, - "sink": { - "start": 6, - "end": 6, - "column": { - "start": 1, - "end": 20 - }, - "content": "axios({ url: url })" - }, - "parent_line_number": 6, - "snippet": "axios({ url: url })", - "fingerprint": "d03323e4c199405710e778b32492501f_0", - "old_fingerprint": "c3fc40c776f8110ab15690122331723a_0", - "code_extract": "axios({ url: url })" - }, - { - "cwe_ids": [ - "918" - ], - "id": "javascript_lang_http_url_using_user_input", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\n\\nApplications should not connect to locations formed from user input.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in HTTP URLs:\\n\\n\`\`\`javascript\\nconst response = axios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nconst hosts = new Map([\\n [\\"option1\\", \\"api1.com\\"],\\n [\\"option2\\", \\"api2.com\\"]\\n])\\n\\nconst host = hosts.get(req.params.host)\\nconst response = axois.get(\`https://\${host}\`)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_url_using_user_input", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 8, - "end": 8, - "column": { - "start": 1, - "end": 15 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 1, - "end": 15 - }, - "content": "axios.get(url)" - }, - "parent_line_number": 8, - "snippet": "axios.get(url)", - "fingerprint": "d03323e4c199405710e778b32492501f_1", - "old_fingerprint": "c3fc40c776f8110ab15690122331723a_1", - "code_extract": "axios.get(url)" - }, - { - "cwe_ids": [ - "918" - ], - "id": "javascript_lang_http_url_using_user_input", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\n\\nApplications should not connect to locations formed from user input.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in HTTP URLs:\\n\\n\`\`\`javascript\\nconst response = axios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nconst hosts = new Map([\\n [\\"option1\\", \\"api1.com\\"],\\n [\\"option2\\", \\"api2.com\\"]\\n])\\n\\nconst host = hosts.get(req.params.host)\\nconst response = axois.get(\`https://\${host}\`)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_url_using_user_input", - "line_number": 13, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 13, - "end": 13, - "column": { - "start": 1, - "end": 11 - } - }, - "sink": { - "start": 13, - "end": 13, - "column": { - "start": 1, - "end": 11 - }, - "content": "fetch(url)" - }, - "parent_line_number": 13, - "snippet": "fetch(url)", - "fingerprint": "d03323e4c199405710e778b32492501f_2", - "old_fingerprint": "c3fc40c776f8110ab15690122331723a_2", - "code_extract": "fetch(url)" - }, - { - "cwe_ids": [ - "918" - ], - "id": "javascript_lang_http_url_using_user_input", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\n\\nApplications should not connect to locations formed from user input.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in HTTP URLs:\\n\\n\`\`\`javascript\\nconst response = axios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nconst hosts = new Map([\\n [\\"option1\\", \\"api1.com\\"],\\n [\\"option2\\", \\"api2.com\\"]\\n])\\n\\nconst host = hosts.get(req.params.host)\\nconst response = axois.get(\`https://\${host}\`)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_url_using_user_input", - "line_number": 19, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 19, - "end": 19, - "column": { - "start": 1, - "end": 23 - } - }, - "sink": { - "start": 19, - "end": 19, - "column": { - "start": 1, - "end": 23 - }, - "content": "xhttp.open('GET', url)" - }, - "parent_line_number": 19, - "snippet": "xhttp.open('GET', url)", - "fingerprint": "d03323e4c199405710e778b32492501f_3", - "old_fingerprint": "c3fc40c776f8110ab15690122331723a_3", - "code_extract": "xhttp.open('GET', url)" - }, - { - "cwe_ids": [ - "918" - ], - "id": "javascript_lang_http_url_using_user_input", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\n\\nApplications should not connect to locations formed from user input.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in HTTP URLs:\\n\\n\`\`\`javascript\\nconst response = axios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nconst hosts = new Map([\\n [\\"option1\\", \\"api1.com\\"],\\n [\\"option2\\", \\"api2.com\\"]\\n])\\n\\nconst host = hosts.get(req.params.host)\\nconst response = axois.get(\`https://\${host}\`)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_url_using_user_input", - "line_number": 25, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 25, - "end": 25, - "column": { - "start": 22, - "end": 38 - } - }, - "sink": { - "start": 25, - "end": 25, - "column": { - "start": 22, - "end": 38 - }, - "content": "request.get(url)" - }, - "parent_line_number": 25, - "snippet": "request.get(url)", - "fingerprint": "d03323e4c199405710e778b32492501f_4", - "old_fingerprint": "c3fc40c776f8110ab15690122331723a_4", - "code_extract": "const imageRequest = request.get(url)" - }, - { - "cwe_ids": [ - "918" - ], - "id": "javascript_lang_http_url_using_user_input", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\n\\nApplications should not connect to locations formed from user input.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in HTTP URLs:\\n\\n\`\`\`javascript\\nconst response = axios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nconst hosts = new Map([\\n [\\"option1\\", \\"api1.com\\"],\\n [\\"option2\\", \\"api2.com\\"]\\n])\\n\\nconst host = hosts.get(req.params.host)\\nconst response = axois.get(\`https://\${host}\`)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_url_using_user_input", - "line_number": 27, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 27, - "end": 27, - "column": { - "start": 1, - "end": 29 - } - }, - "sink": { - "start": 27, - "end": 27, - "column": { - "start": 1, - "end": 29 - }, - "content": "request(url, function () {})" - }, - "parent_line_number": 27, - "snippet": "request(url, function () {})", - "fingerprint": "d03323e4c199405710e778b32492501f_5", - "old_fingerprint": "c3fc40c776f8110ab15690122331723a_5", - "code_extract": "request(url, function () {})" - }, - { - "cwe_ids": [ - "918" - ], - "id": "javascript_lang_http_url_using_user_input", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\n\\nApplications should not connect to locations formed from user input.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in HTTP URLs:\\n\\n\`\`\`javascript\\nconst response = axios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nconst hosts = new Map([\\n [\\"option1\\", \\"api1.com\\"],\\n [\\"option2\\", \\"api2.com\\"]\\n])\\n\\nconst host = hosts.get(req.params.host)\\nconst response = axois.get(\`https://\${host}\`)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_url_using_user_input", - "line_number": 31, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 31, - "end": 31, - "column": { - "start": 3, - "end": 23 - } - }, - "sink": { - "start": 31, - "end": 31, - "column": { - "start": 3, - "end": 23 - }, - "content": "axios.get(event.url)" - }, - "parent_line_number": 31, - "snippet": "axios.get(event.url)", - "fingerprint": "d03323e4c199405710e778b32492501f_6", - "old_fingerprint": "c3fc40c776f8110ab15690122331723a_6", - "code_extract": " axios.get(event.url)" - }, - { - "cwe_ids": [ - "918" - ], - "id": "javascript_lang_http_url_using_user_input", - "title": "Unsanitized user input in HTTP request (SSRF)", - "description": "## Description\\n\\nApplications should not connect to locations formed from user input.\\nThis rule checks for URLs containing user-supplied data.\\n\\n## Remediations\\n\\n❌ Avoid using user input in HTTP URLs:\\n\\n\`\`\`javascript\\nconst response = axios.get(\`https://\${req.params.host}\`)\\n\`\`\`\\n\\n✅ Use user input indirectly to form a URL:\\n\\n\`\`\`javascript\\nconst hosts = new Map([\\n [\\"option1\\", \\"api1.com\\"],\\n [\\"option2\\", \\"api2.com\\"]\\n])\\n\\nconst host = hosts.get(req.params.host)\\nconst response = axois.get(\`https://\${host}\`)\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_http_url_using_user_input", - "line_number": 35, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 35, - "end": 35, - "column": { - "start": 3, - "end": 26 - } - }, - "sink": { - "start": 35, - "end": 35, - "column": { - "start": 3, - "end": 26 - }, - "content": "axios.get(event[\\"url\\"])" - }, - "parent_line_number": 35, - "snippet": "axios.get(event[\\"url\\"])", - "fingerprint": "d03323e4c199405710e778b32492501f_7", - "old_fingerprint": "c3fc40c776f8110ab15690122331723a_7", - "code_extract": " axios.get(event[\\"url\\"])" - } - ] -}" -`; - -exports[`javascript_lang_http_url_using_user_input ok 1`] = `"{}"`; diff --git a/tests/javascript/lang/http_url_using_user_input/test.js b/tests/javascript/lang/http_url_using_user_input/test.js index fa284d13a..fc42999a0 100644 --- a/tests/javascript/lang/http_url_using_user_input/test.js +++ b/tests/javascript/lang/http_url_using_user_input/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.js" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/http_url_using_user_input/testdata/bad.js b/tests/javascript/lang/http_url_using_user_input/testdata/bad.js index 28d549283..2382b0592 100644 --- a/tests/javascript/lang/http_url_using_user_input/testdata/bad.js +++ b/tests/javascript/lang/http_url_using_user_input/testdata/bad.js @@ -3,34 +3,42 @@ const url = req.body.imageUrl // Axios +// bearer:expected javascript_lang_http_url_using_user_input axios({ url: url }) +// bearer:expected javascript_lang_http_url_using_user_input axios.get(url) // Fetch +// bearer:expected javascript_lang_http_url_using_user_input fetch(url) // XMLHttpRequest var xhttp = new XMLHttpRequest() +// bearer:expected javascript_lang_http_url_using_user_input xhttp.open('GET', url) // Request const request = require('request') +// bearer:expected javascript_lang_http_url_using_user_input const imageRequest = request.get(url) +// bearer:expected javascript_lang_http_url_using_user_input request(url, function () {}) export const handler = async (event, context) => { +// bearer:expected javascript_lang_http_url_using_user_input axios.get(event.url) } exports.handler = async function (event, context) { +// bearer:expected javascript_lang_http_url_using_user_input axios.get(event["url"]) } diff --git a/tests/javascript/lang/import_using_user_input/__snapshots__/test.js.snap b/tests/javascript/lang/import_using_user_input/__snapshots__/test.js.snap deleted file mode 100644 index d607a03db..000000000 --- a/tests/javascript/lang/import_using_user_input/__snapshots__/test.js.snap +++ /dev/null @@ -1,119 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_import_using_user_input ok_known_resource 1`] = `"{}"`; - -exports[`javascript_lang_import_using_user_input require_destructured_resource 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "470" - ], - "id": "javascript_lang_import_using_user_input", - "title": "Usage of externally controlled input to select code", - "description": "## Description\\n\\nLoading code dynamically from a path formed from user input can allow an\\nattacker to execute arbitrary code.\\n\\n## Remediations\\n\\n❌ Avoid passing user or request input to require().\\n\\n✅ Where it is unavoidable to rely on user input, sanitize the input or use a safelist\\n\\n\`\`\`javascript\\nvar path = req.body.path\\nif (['users', 'posts', 'pages'].includes(path)) {\\n require(\`\${path}.js\`)\\n}\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_import_using_user_input", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/require_destructured_resource.js", - "filename": ".", - "source": { - "start": 7, - "end": 7, - "column": { - "start": 3, - "end": 16 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 3, - "end": 16 - }, - "content": "require(path)" - }, - "parent_line_number": 7, - "snippet": "require(path)", - "fingerprint": "ce8a5417c71d4166a93f05ca32da7883_0", - "old_fingerprint": "d110bd47bf4a579b94604413a38a5bf7_0", - "code_extract": "\\t\\trequire(path);" - } - ] -}" -`; - -exports[`javascript_lang_import_using_user_input require_external_resource 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "470" - ], - "id": "javascript_lang_import_using_user_input", - "title": "Usage of externally controlled input to select code", - "description": "## Description\\n\\nLoading code dynamically from a path formed from user input can allow an\\nattacker to execute arbitrary code.\\n\\n## Remediations\\n\\n❌ Avoid passing user or request input to require().\\n\\n✅ Where it is unavoidable to rely on user input, sanitize the input or use a safelist\\n\\n\`\`\`javascript\\nvar path = req.body.path\\nif (['users', 'posts', 'pages'].includes(path)) {\\n require(\`\${path}.js\`)\\n}\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_import_using_user_input", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/require_external_resource.js", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 5, - "end": 33 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 5, - "end": 33 - }, - "content": "require(req.query.user.path)" - }, - "parent_line_number": 10, - "snippet": "require(req.query.user.path)", - "fingerprint": "ce8a5417c71d4166a93f05ca32da7883_0", - "old_fingerprint": "e26d7c8e16a0427a93ddc87b40c1fc6c_0", - "code_extract": " require(req.query.user.path)" - }, - { - "cwe_ids": [ - "470" - ], - "id": "javascript_lang_import_using_user_input", - "title": "Usage of externally controlled input to select code", - "description": "## Description\\n\\nLoading code dynamically from a path formed from user input can allow an\\nattacker to execute arbitrary code.\\n\\n## Remediations\\n\\n❌ Avoid passing user or request input to require().\\n\\n✅ Where it is unavoidable to rely on user input, sanitize the input or use a safelist\\n\\n\`\`\`javascript\\nvar path = req.body.path\\nif (['users', 'posts', 'pages'].includes(path)) {\\n require(\`\${path}.js\`)\\n}\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_import_using_user_input", - "line_number": 15, - "full_filename": "/tmp/bearer-scan/require_external_resource.js", - "filename": ".", - "source": { - "start": 15, - "end": 15, - "column": { - "start": 3, - "end": 30 - } - }, - "sink": { - "start": 15, - "end": 15, - "column": { - "start": 3, - "end": 30 - }, - "content": "import(req.query.user.path)" - }, - "parent_line_number": 15, - "snippet": "import(req.query.user.path)", - "fingerprint": "ce8a5417c71d4166a93f05ca32da7883_1", - "old_fingerprint": "e26d7c8e16a0427a93ddc87b40c1fc6c_1", - "code_extract": " import(req.query.user.path)" - } - ] -}" -`; diff --git a/tests/javascript/lang/import_using_user_input/test.js b/tests/javascript/lang/import_using_user_input/test.js index 4a83a38e3..6594cf8f0 100644 --- a/tests/javascript/lang/import_using_user_input/test.js +++ b/tests/javascript/lang/import_using_user_input/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("ok_known_resource", () => { + const testCase = "ok_known_resource.js" + + const results = invoke(testCase) - test("ok_known_resource", () => { - const testCase = "ok_known_resource.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("require_destructured_resource", () => { - const testCase = "require_destructured_resource.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("require_destructured_resource", () => { + const testCase = "require_destructured_resource.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("require_external_resource", () => { - const testCase = "require_external_resource.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("require_external_resource", () => { + const testCase = "require_external_resource.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/import_using_user_input/testdata/require_destructured_resource.js b/tests/javascript/lang/import_using_user_input/testdata/require_destructured_resource.js index a9a12082c..dd212e961 100644 --- a/tests/javascript/lang/import_using_user_input/testdata/require_destructured_resource.js +++ b/tests/javascript/lang/import_using_user_input/testdata/require_destructured_resource.js @@ -4,6 +4,7 @@ app.get("/bad", (req, _res) => { try { const { path } = req.query; +// bearer:expected javascript_lang_import_using_user_input require(path); } catch (err) { // handle error diff --git a/tests/javascript/lang/import_using_user_input/testdata/require_external_resource.js b/tests/javascript/lang/import_using_user_input/testdata/require_external_resource.js index adc5fce3c..564358b95 100644 --- a/tests/javascript/lang/import_using_user_input/testdata/require_external_resource.js +++ b/tests/javascript/lang/import_using_user_input/testdata/require_external_resource.js @@ -7,10 +7,12 @@ app.use(helmet.hidePoweredBy()) app.get("/bad", (req, _res) => { try { +// bearer:expected javascript_lang_import_using_user_input require(req.query.user.path) } catch (err) { // handle error } +// bearer:expected javascript_lang_import_using_user_input import(req.query.user.path) }) diff --git a/tests/javascript/lang/jwt/__snapshots__/test.js.snap b/tests/javascript/lang/jwt/__snapshots__/test.js.snap deleted file mode 100644 index fda19f4e0..000000000 --- a/tests/javascript/lang/jwt/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_jwt insecure 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "312" - ], - "id": "javascript_lang_jwt", - "title": "Leakage of sensitive data in JWT", - "description": "## Description\\n\\nJWTs are not a secure place to store sensitive data. This rule looks for any sensitive data types saved to a JWT.\\n\\n## Remediations\\n\\n❌ Avoid storing sensitive data in JWTs:\\n\\n\`\`\`javascript\\n const jwt = require('jsonwebtoken');\\n const token = jwt.sign({ user: { email: 'jhon@gmail.com' }});\\n\`\`\`\\n\\n✅ If you need to store user's information, use their unique database identifier instead of personal identifiable information:\\n\\n\`\`\`javascript\\n const jwt = require('jsonwebtoken');\\n const token = jwt.sign({ user: user.uuid });\\n\`\`\`\\n\\n## Resources\\n - [OWASP sensitive data exposure](https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_jwt", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 12, - "end": 35 - } - }, - "sink": { - "start": 2, - "end": 5, - "column": { - "start": 13, - "end": 2 - }, - "content": "jwt.sign(\\n\\t{ user: { email: \\"jhon@gmail.com\\" } },\\n\\tprocess.env.JWT_SECRET\\n)" - }, - "parent_line_number": 2, - "snippet": "jwt.sign(\\n\\t{ user: { email: \\"jhon@gmail.com\\" } },\\n\\tprocess.env.JWT_SECRET\\n)", - "fingerprint": "a07bf92978c23dd3276b9f99c6468078_0", - "old_fingerprint": "033a53b024d0cc266ed79667e570c3ba_0", - "code_extract": "var token = jwt.sign(\\n\\t{ user: { email: \\"jhon@gmail.com\\" } },\\n\\tprocess.env.JWT_SECRET\\n);" - } - ] -}" -`; - -exports[`javascript_lang_jwt secure 1`] = `"{}"`; diff --git a/tests/javascript/lang/jwt/test.js b/tests/javascript/lang/jwt/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/lang/jwt/test.js +++ b/tests/javascript/lang/jwt/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/jwt/testdata/insecure.js b/tests/javascript/lang/jwt/testdata/insecure.js index 07cf4b150..4ca5e4e6e 100644 --- a/tests/javascript/lang/jwt/testdata/insecure.js +++ b/tests/javascript/lang/jwt/testdata/insecure.js @@ -1,4 +1,5 @@ var jwt = require("jsonwebtoken"); +// bearer:expected javascript_lang_jwt var token = jwt.sign( { user: { email: "jhon@gmail.com" } }, process.env.JWT_SECRET diff --git a/tests/javascript/lang/jwt_hardcoded_secret/__snapshots__/test.js.snap b/tests/javascript/lang/jwt_hardcoded_secret/__snapshots__/test.js.snap deleted file mode 100644 index de1fe81e9..000000000 --- a/tests/javascript/lang/jwt_hardcoded_secret/__snapshots__/test.js.snap +++ /dev/null @@ -1,160 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_jwt_hardcoded_secret insecure 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_jwt_hardcoded_secret", - "title": "Leakage of hard-coded secret in JWT", - "description": "## Description\\n\\nCode is not a secure place to store secrets, use environment variables instead.\\n\\n## Remediations\\n\\nUse environment variables\\n\\n\`\`\`javascript\\n var jwt = require(\\"jsonwebtoken\\");\\n\\n var token = jwt.sign({ foo: \\"bar\\" }, process.env.JWT_SECRET);\\n\`\`\`\\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/javascript_lang_jwt_hardcoded_secret", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 13, - "end": 51 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 13, - "end": 51 - }, - "content": "jwt.sign({ foo: \\"bar\\" }, \\"someSecret\\")" - }, - "parent_line_number": 3, - "snippet": "jwt.sign({ foo: \\"bar\\" }, \\"someSecret\\")", - "fingerprint": "d0029fa61eca40823af6b8a00901cfaf_0", - "old_fingerprint": "ef25e950f616899c3627380e235b558c_0", - "code_extract": "var token = jwt.sign({ foo: \\"bar\\" }, \\"someSecret\\");" - } - ] -}" -`; - -exports[`javascript_lang_jwt_hardcoded_secret insecure_jose_jwt 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_jwt_hardcoded_secret", - "title": "Leakage of hard-coded secret in JWT", - "description": "## Description\\n\\nCode is not a secure place to store secrets, use environment variables instead.\\n\\n## Remediations\\n\\nUse environment variables\\n\\n\`\`\`javascript\\n var jwt = require(\\"jsonwebtoken\\");\\n\\n var token = jwt.sign({ foo: \\"bar\\" }, process.env.JWT_SECRET);\\n\`\`\`\\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/javascript_lang_jwt_hardcoded_secret", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/insecure_jose_jwt.js", - "filename": ".", - "source": { - "start": 5, - "end": 8, - "column": { - "start": 19, - "end": 16 - } - }, - "sink": { - "start": 5, - "end": 8, - "column": { - "start": 19, - "end": 16 - }, - "content": "new jose.SignJWT({ 'urn:example:claim': true })\\n .setIssuedAt()\\n .setExpirationTime('2h')\\n .sign(secret)" - }, - "parent_line_number": 5, - "snippet": "new jose.SignJWT({ 'urn:example:claim': true })\\n .setIssuedAt()\\n .setExpirationTime('2h')\\n .sign(secret)", - "fingerprint": "d0029fa61eca40823af6b8a00901cfaf_0", - "old_fingerprint": "0821f1feacde43f91832d6ae43918279_0", - "code_extract": "const jwt = await new jose.SignJWT({ 'urn:example:claim': true })\\n .setIssuedAt()\\n .setExpirationTime('2h')\\n .sign(secret)" - }, - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_jwt_hardcoded_secret", - "title": "Leakage of hard-coded secret in JWT", - "description": "## Description\\n\\nCode is not a secure place to store secrets, use environment variables instead.\\n\\n## Remediations\\n\\nUse environment variables\\n\\n\`\`\`javascript\\n var jwt = require(\\"jsonwebtoken\\");\\n\\n var token = jwt.sign({ foo: \\"bar\\" }, process.env.JWT_SECRET);\\n\`\`\`\\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/javascript_lang_jwt_hardcoded_secret", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/insecure_jose_jwt.js", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 20, - "end": 53 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 20, - "end": 53 - }, - "content": "(new jose.SignJWT()).sign(secret)" - }, - "parent_line_number": 10, - "snippet": "(new jose.SignJWT()).sign(secret)", - "fingerprint": "d0029fa61eca40823af6b8a00901cfaf_1", - "old_fingerprint": "0821f1feacde43f91832d6ae43918279_1", - "code_extract": "const jwt2 = await (new jose.SignJWT()).sign(secret)" - } - ] -}" -`; - -exports[`javascript_lang_jwt_hardcoded_secret insecure_jwt 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "798" - ], - "id": "javascript_lang_jwt_hardcoded_secret", - "title": "Leakage of hard-coded secret in JWT", - "description": "## Description\\n\\nCode is not a secure place to store secrets, use environment variables instead.\\n\\n## Remediations\\n\\nUse environment variables\\n\\n\`\`\`javascript\\n var jwt = require(\\"jsonwebtoken\\");\\n\\n var token = jwt.sign({ foo: \\"bar\\" }, process.env.JWT_SECRET);\\n\`\`\`\\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/javascript_lang_jwt_hardcoded_secret", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/insecure_jwt.js", - "filename": ".", - "source": { - "start": 6, - "end": 6, - "column": { - "start": 3, - "end": 81 - } - }, - "sink": { - "start": 6, - "end": 6, - "column": { - "start": 3, - "end": 81 - }, - "content": "myJWT.sign(user, privateKey, { expiresInMinutes: 60 * 5, algorithm: \\"RS256\\" })" - }, - "parent_line_number": 6, - "snippet": "myJWT.sign(user, privateKey, { expiresInMinutes: 60 * 5, algorithm: \\"RS256\\" })", - "fingerprint": "d0029fa61eca40823af6b8a00901cfaf_0", - "old_fingerprint": "6c80799d9ecd67e779a8a69f88fd87c4_0", - "code_extract": " myJWT.sign(user, privateKey, { expiresInMinutes: 60 * 5, algorithm: \\"RS256\\" })" - } - ] -}" -`; - -exports[`javascript_lang_jwt_hardcoded_secret secure 1`] = `"{}"`; diff --git a/tests/javascript/lang/jwt_hardcoded_secret/test.js b/tests/javascript/lang/jwt_hardcoded_secret/test.js index 76c8e2bca..fc57fc449 100644 --- a/tests/javascript/lang/jwt_hardcoded_secret/test.js +++ b/tests/javascript/lang/jwt_hardcoded_secret/test.js @@ -1,31 +1,50 @@ -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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("insecure_jose_jwt", () => { - const testCase = "insecure_jose_jwt.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure_jose_jwt", () => { + const testCase = "insecure_jose_jwt.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("insecure_jwt", () => { - const testCase = "insecure_jwt.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("insecure_jwt", () => { + const testCase = "insecure_jwt.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure.js b/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure.js index 1f8e31e90..17e6dea70 100644 --- a/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure.js +++ b/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure.js @@ -1,3 +1,4 @@ var jwt = require("jsonwebtoken"); +// bearer:expected javascript_lang_jwt_hardcoded_secret var token = jwt.sign({ foo: "bar" }, "someSecret"); diff --git a/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure_jose_jwt.js b/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure_jose_jwt.js index f851358b4..bd1352bfb 100644 --- a/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure_jose_jwt.js +++ b/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure_jose_jwt.js @@ -2,11 +2,13 @@ import * as jose from 'jose' const secret = "my-hardcoded-secret" +// bearer:expected javascript_lang_jwt_hardcoded_secret const jwt = await new jose.SignJWT({ 'urn:example:claim': true }) .setIssuedAt() .setExpirationTime('2h') .sign(secret) +// bearer:expected javascript_lang_jwt_hardcoded_secret const jwt2 = await (new jose.SignJWT()).sign(secret) console.log(jwt) diff --git a/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure_jwt.js b/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure_jwt.js index fae40ed75..ffd50d35c 100644 --- a/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure_jwt.js +++ b/tests/javascript/lang/jwt_hardcoded_secret/testdata/insecure_jwt.js @@ -3,4 +3,5 @@ const privateKey = "-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----" exports.authorize = (user = {}) => +// bearer:expected javascript_lang_jwt_hardcoded_secret myJWT.sign(user, privateKey, { expiresInMinutes: 60 * 5, algorithm: "RS256" }) diff --git a/tests/javascript/lang/jwt_weak_encryption/__snapshots__/test.js.snap b/tests/javascript/lang/jwt_weak_encryption/__snapshots__/test.js.snap deleted file mode 100644 index 8ebcb805c..000000000 --- a/tests/javascript/lang/jwt_weak_encryption/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_jwt_weak_encryption insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "327" - ], - "id": "javascript_lang_jwt_weak_encryption", - "title": "Usage of weak encryption algorithm in JWT", - "description": "## Description\\n\\nUse any default encryption algorithm jwt library provides\\n\\n## Remediations\\n\\nUse the HS256 algorithm for JWT encryption\\n\\n\`\`\`\\n jwt.sign({ \\"foo\\": \\"bar\\"}, process.env.JWT_SECRET, {\\n algorithm: \\"HS256\\"\\n })\\n\`\`\`\\n\\n## Resources\\n- [OWASP weak encryption](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)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_jwt_weak_encryption", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "source": { - "start": 3, - "end": 5, - "column": { - "start": 13, - "end": 3 - } - }, - "sink": { - "start": 3, - "end": 5, - "column": { - "start": 13, - "end": 3 - }, - "content": "jwt.sign({ foo: \\"bar\\" }, process.env.JWT_SECRET, {\\n\\talgorithm: \\"none\\",\\n})" - }, - "parent_line_number": 3, - "snippet": "jwt.sign({ foo: \\"bar\\" }, process.env.JWT_SECRET, {\\n\\talgorithm: \\"none\\",\\n})", - "fingerprint": "4a605c6c148c868f59c5f8060462cf2d_0", - "old_fingerprint": "010757aec840934f5b262a8bb139ba29_0", - "code_extract": "var token = jwt.sign({ foo: \\"bar\\" }, process.env.JWT_SECRET, {\\n\\talgorithm: \\"none\\",\\n});" - } - ] -}" -`; - -exports[`javascript_lang_jwt_weak_encryption secure 1`] = `"{}"`; diff --git a/tests/javascript/lang/jwt_weak_encryption/test.js b/tests/javascript/lang/jwt_weak_encryption/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/lang/jwt_weak_encryption/test.js +++ b/tests/javascript/lang/jwt_weak_encryption/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/jwt_weak_encryption/testdata/insecure.js b/tests/javascript/lang/jwt_weak_encryption/testdata/insecure.js index bf9521337..9d21b5265 100644 --- a/tests/javascript/lang/jwt_weak_encryption/testdata/insecure.js +++ b/tests/javascript/lang/jwt_weak_encryption/testdata/insecure.js @@ -1,5 +1,6 @@ var jwt = require("jsonwebtoken"); +// bearer:expected javascript_lang_jwt_weak_encryption var token = jwt.sign({ foo: "bar" }, process.env.JWT_SECRET, { algorithm: "none", }); diff --git a/tests/javascript/lang/logger/__snapshots__/test.js.snap b/tests/javascript/lang/logger/__snapshots__/test.js.snap deleted file mode 100644 index c31151c00..000000000 --- a/tests/javascript/lang/logger/__snapshots__/test.js.snap +++ /dev/null @@ -1,292 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_logger child 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "532" - ], - "id": "javascript_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\`\`\`javascript\\nlogger.info(\`User is: \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nlogger.info(\`User is: \${user.uuid}\`)\\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/javascript_lang_logger", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/child.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 3, - "end": 27 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 1, - "end": 18 - }, - "content": "logger.child(ctx)" - }, - "parent_line_number": 7, - "snippet": "logger.child(ctx)", - "fingerprint": "327449cd47ed82672cc47bf9cfccdb4a_0", - "old_fingerprint": "75088f50d0c8c96afbea96e5a2bfbb74_0", - "code_extract": "logger.child(ctx);" - } - ] -}" -`; - -exports[`javascript_lang_logger child_level 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "532" - ], - "id": "javascript_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\`\`\`javascript\\nlogger.info(\`User is: \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nlogger.info(\`User is: \${user.uuid}\`)\\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/javascript_lang_logger", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/child_level.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 7, - "end": 7, - "column": { - "start": 24, - "end": 33 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 1, - "end": 34 - }, - "content": "logger.child(ctx).info(user.name)" - }, - "parent_line_number": 7, - "snippet": "logger.child(ctx).info(user.name)", - "fingerprint": "327449cd47ed82672cc47bf9cfccdb4a_0", - "old_fingerprint": "02e247f69b1c812c168a85bc9af2be8d_0", - "code_extract": "logger.child(ctx).info(user.name);" - } - ] -}" -`; - -exports[`javascript_lang_logger console 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "532" - ], - "id": "javascript_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\`\`\`javascript\\nlogger.info(\`User is: \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nlogger.info(\`User is: \${user.uuid}\`)\\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/javascript_lang_logger", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/console.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 1, - "end": 1, - "column": { - "start": 13, - "end": 22 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 23 - }, - "content": "console.log(user.name)" - }, - "parent_line_number": 1, - "snippet": "console.log(user.name)", - "fingerprint": "327449cd47ed82672cc47bf9cfccdb4a_0", - "old_fingerprint": "378108517b74500d91317c3001e7edf2_0", - "code_extract": "console.log(user.name)" - }, - { - "cwe_ids": [ - "532" - ], - "id": "javascript_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\`\`\`javascript\\nlogger.info(\`User is: \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nlogger.info(\`User is: \${user.uuid}\`)\\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/javascript_lang_logger", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/console.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 2, - "end": 2, - "column": { - "start": 30, - "end": 40 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 1, - "end": 41 - }, - "content": "console.log(\\"user email is\\", user.email)" - }, - "parent_line_number": 2, - "snippet": "console.log(\\"user email is\\", user.email)", - "fingerprint": "327449cd47ed82672cc47bf9cfccdb4a_1", - "old_fingerprint": "378108517b74500d91317c3001e7edf2_1", - "code_extract": "console.log(\\"user email is\\", user.email)" - } - ] -}" -`; - -exports[`javascript_lang_logger datatype_leak 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "532" - ], - "id": "javascript_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\`\`\`javascript\\nlogger.info(\`User is: \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nlogger.info(\`User is: \${user.uuid}\`)\\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/javascript_lang_logger", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/datatype_leak.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 1, - "end": 1, - "column": { - "start": 13, - "end": 23 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 24 - }, - "content": "logger.info(user.email)" - }, - "parent_line_number": 1, - "snippet": "logger.info(user.email)", - "fingerprint": "327449cd47ed82672cc47bf9cfccdb4a_0", - "old_fingerprint": "a8e78221aec2fca81292bfd15370d686_0", - "code_extract": "logger.info(user.email)" - } - ] -}" -`; - -exports[`javascript_lang_logger log 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "532" - ], - "id": "javascript_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\`\`\`javascript\\nlogger.info(\`User is: \${user.email}\`)\\n\`\`\`\\n\\n✅ If you need to identify a user, use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\nlogger.info(\`User is: \${user.uuid}\`)\\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/javascript_lang_logger", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/log.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 1, - "end": 1, - "column": { - "start": 10, - "end": 19 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 20 - }, - "content": "log.info(user.name)" - }, - "parent_line_number": 1, - "snippet": "log.info(user.name)", - "fingerprint": "327449cd47ed82672cc47bf9cfccdb4a_0", - "old_fingerprint": "723726a459dfed5a2d43f971770ff0f4_0", - "code_extract": "log.info(user.name);" - } - ] -}" -`; - -exports[`javascript_lang_logger ok_no_datatypes 1`] = `"{}"`; - -exports[`javascript_lang_logger shared_datatype 1`] = `"{}"`; diff --git a/tests/javascript/lang/logger/test.js b/tests/javascript/lang/logger/test.js index 9f4076745..77bfde1e8 100644 --- a/tests/javascript/lang/logger/test.js +++ b/tests/javascript/lang/logger/test.js @@ -1,48 +1,80 @@ -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("child", () => { + const testCase = "child.js" - test("child", () => { - const testCase = "child.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + const results = invoke(testCase) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - test("child_level", () => { - const testCase = "child_level.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("child_level", () => { + const testCase = "child_level.js" + const results = invoke(testCase) - test("console", () => { - const testCase = "console.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + test("console", () => { + const testCase = "console.js" - test("datatype_leak", () => { - const testCase = "datatype_leak.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + const results = invoke(testCase) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + - test("log", () => { - const testCase = "log.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_leak", () => { + const testCase = "datatype_leak.js" + const results = invoke(testCase) - test("ok_no_datatypes", () => { - const testCase = "ok_no_datatypes.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + test("log", () => { + const testCase = "log.js" - test("shared_datatype", () => { - const testCase = "shared_datatype.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) -}) + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("ok_no_datatypes", () => { + const testCase = "ok_no_datatypes.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("shared_datatype", () => { + const testCase = "shared_datatype.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + +}) \ No newline at end of file diff --git a/tests/javascript/lang/logger/testdata/child.js b/tests/javascript/lang/logger/testdata/child.js index cd2bb0a98..88d707da5 100644 --- a/tests/javascript/lang/logger/testdata/child.js +++ b/tests/javascript/lang/logger/testdata/child.js @@ -4,4 +4,5 @@ const ctx = { }, }; +// bearer:expected javascript_lang_logger logger.child(ctx); diff --git a/tests/javascript/lang/logger/testdata/child_level.js b/tests/javascript/lang/logger/testdata/child_level.js index 434f33ac3..16cc3e6d6 100644 --- a/tests/javascript/lang/logger/testdata/child_level.js +++ b/tests/javascript/lang/logger/testdata/child_level.js @@ -4,4 +4,5 @@ const ctx = { }, }; +// bearer:expected javascript_lang_logger logger.child(ctx).info(user.name); diff --git a/tests/javascript/lang/logger/testdata/console.js b/tests/javascript/lang/logger/testdata/console.js index a88d4a8e5..0295dd1b9 100644 --- a/tests/javascript/lang/logger/testdata/console.js +++ b/tests/javascript/lang/logger/testdata/console.js @@ -1,3 +1,5 @@ +// bearer:expected javascript_lang_logger console.log(user.name) +// bearer:expected javascript_lang_logger console.log("user email is", user.email) console.log(user.name ? ok : ok) diff --git a/tests/javascript/lang/logger/testdata/datatype_leak.js b/tests/javascript/lang/logger/testdata/datatype_leak.js index e6ceec591..59e2fe207 100644 --- a/tests/javascript/lang/logger/testdata/datatype_leak.js +++ b/tests/javascript/lang/logger/testdata/datatype_leak.js @@ -1 +1,2 @@ +// bearer:expected javascript_lang_logger logger.info(user.email) \ No newline at end of file diff --git a/tests/javascript/lang/logger/testdata/log.js b/tests/javascript/lang/logger/testdata/log.js index fc4e30d28..37c7133dd 100644 --- a/tests/javascript/lang/logger/testdata/log.js +++ b/tests/javascript/lang/logger/testdata/log.js @@ -1 +1,2 @@ +// bearer:expected javascript_lang_logger log.info(user.name); diff --git a/tests/javascript/lang/manual_html_sanitization/__snapshots__/test.js.snap b/tests/javascript/lang/manual_html_sanitization/__snapshots__/test.js.snap deleted file mode 100644 index d6fd6725b..000000000 --- a/tests/javascript/lang/manual_html_sanitization/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_manual_html_sanitization safe 1`] = `"{}"`; - -exports[`javascript_lang_manual_html_sanitization unsafe 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_manual_html_sanitization", - "title": "Usage of manual HTML sanitization (XSS)", - "description": "## Description\\nSanitizing HTML manually is error prone and can lead to Cross Site\\nScripting (XSS) vulnerabilities.\\n\\n## Remediations\\n\\n❌ Avoid manually escaping HTML:\\n\\n\`\`\`javascript\\nconst sanitizedUserInput = user.Input\\n .replaceAll('<', '<')\\n .replaceAll('>', '>');\\nconst html = \`\${sanitizedUserInput}\`;\\n\`\`\`\\n\\n✅ Use a HTML sanitization library:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html';\\n\\nconst html = sanitizeHtml(\`\${user.Input}\`);\\n\`\`\`\\n\\n## Resources\\n- [OWASP XSS explained](https://owasp.org/www-community/attacks/xss/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_manual_html_sanitization", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/unsafe.js", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 28, - "end": 86 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 28, - "end": 62 - }, - "content": "user.Input.replaceAll('<', '<')" - }, - "parent_line_number": 1, - "snippet": "user.Input.replaceAll('<', '<')", - "fingerprint": "883581e9effcc89f50531cd2677ebf31_0", - "old_fingerprint": "f64354c034f32ea4927e1f751b63cb3b_0", - "code_extract": "const sanitizedUserInput = user.Input.replaceAll('<', '<').replaceAll('>', '>');" - } - ] -}" -`; diff --git a/tests/javascript/lang/manual_html_sanitization/test.js b/tests/javascript/lang/manual_html_sanitization/test.js index c76f1f3ab..febe7c965 100644 --- a/tests/javascript/lang/manual_html_sanitization/test.js +++ b/tests/javascript/lang/manual_html_sanitization/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("safe", () => { + const testCase = "safe.js" + + const results = invoke(testCase) - test("safe", () => { - const testCase = "safe.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("unsafe", () => { - const testCase = "unsafe.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("unsafe", () => { + const testCase = "unsafe.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/manual_html_sanitization/testdata/unsafe.js b/tests/javascript/lang/manual_html_sanitization/testdata/unsafe.js index b47e1e123..431aed994 100644 --- a/tests/javascript/lang/manual_html_sanitization/testdata/unsafe.js +++ b/tests/javascript/lang/manual_html_sanitization/testdata/unsafe.js @@ -1,2 +1,3 @@ +// bearer:expected javascript_lang_manual_html_sanitization const sanitizedUserInput = user.Input.replaceAll('<', '<').replaceAll('>', '>'); const html = `${sanitizedUserInput}`; diff --git a/tests/javascript/lang/message_handler_origin/__snapshots__/test.js.snap b/tests/javascript/lang/message_handler_origin/__snapshots__/test.js.snap deleted file mode 100644 index 6e7e2bb46..000000000 --- a/tests/javascript/lang/message_handler_origin/__snapshots__/test.js.snap +++ /dev/null @@ -1,112 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_message_handler_origin bad 1`] = ` -"{ - "medium": [ - { - "cwe_ids": [ - "346" - ], - "id": "javascript_lang_message_handler_origin", - "title": "Missing origin check in message handler", - "description": "## Description\\n\\nApplications should check the origin of \`message\` events. Handling messages\\nfrom untrusted origins could lead to Cross-Site Scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid handling messages from any origin:\\n\\n\`\`\`javascript\\nwindow.addEventListener('message', (event) => {\\n actOnMessage(event.data)\\n})\\n\`\`\`\\n\\n✅ Validate the origin:\\n\\n\`\`\`javascript\\nwindow.addEventListener('message', (event) => {\\n if (event.origin != 'https://myapp.example.com') {\\n throw new Error('invalid origin')\\n }\\n\\n actOnMessage(event.data)\\n})\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_message_handler_origin", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 1, - "end": 3, - "column": { - "start": 1, - "end": 3 - } - }, - "sink": { - "start": 1, - "end": 3, - "column": { - "start": 1, - "end": 3 - }, - "content": "window.addEventListener('message', (event) => {\\n actOnMessage(event.data)\\n})" - }, - "parent_line_number": 1, - "snippet": "window.addEventListener('message', (event) => {\\n actOnMessage(event.data)\\n})", - "fingerprint": "4ac5e012a055ff87b9c6ec59be0139aa_0", - "old_fingerprint": "a8447e4b3d7e807590f9509e24e4470b_0", - "code_extract": "window.addEventListener('message', (event) => {\\n actOnMessage(event.data)\\n})" - }, - { - "cwe_ids": [ - "346" - ], - "id": "javascript_lang_message_handler_origin", - "title": "Missing origin check in message handler", - "description": "## Description\\n\\nApplications should check the origin of \`message\` events. Handling messages\\nfrom untrusted origins could lead to Cross-Site Scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid handling messages from any origin:\\n\\n\`\`\`javascript\\nwindow.addEventListener('message', (event) => {\\n actOnMessage(event.data)\\n})\\n\`\`\`\\n\\n✅ Validate the origin:\\n\\n\`\`\`javascript\\nwindow.addEventListener('message', (event) => {\\n if (event.origin != 'https://myapp.example.com') {\\n throw new Error('invalid origin')\\n }\\n\\n actOnMessage(event.data)\\n})\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_message_handler_origin", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 5, - "end": 7, - "column": { - "start": 1, - "end": 3 - } - }, - "sink": { - "start": 5, - "end": 7, - "column": { - "start": 1, - "end": 3 - }, - "content": "addEventListener('message', function (event) {\\n actOnMessage(event.data)\\n})" - }, - "parent_line_number": 5, - "snippet": "addEventListener('message', function (event) {\\n actOnMessage(event.data)\\n})", - "fingerprint": "4ac5e012a055ff87b9c6ec59be0139aa_1", - "old_fingerprint": "a8447e4b3d7e807590f9509e24e4470b_1", - "code_extract": "addEventListener('message', function (event) {\\n actOnMessage(event.data)\\n})" - }, - { - "cwe_ids": [ - "346" - ], - "id": "javascript_lang_message_handler_origin", - "title": "Missing origin check in message handler", - "description": "## Description\\n\\nApplications should check the origin of \`message\` events. Handling messages\\nfrom untrusted origins could lead to Cross-Site Scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid handling messages from any origin:\\n\\n\`\`\`javascript\\nwindow.addEventListener('message', (event) => {\\n actOnMessage(event.data)\\n})\\n\`\`\`\\n\\n✅ Validate the origin:\\n\\n\`\`\`javascript\\nwindow.addEventListener('message', (event) => {\\n if (event.origin != 'https://myapp.example.com') {\\n throw new Error('invalid origin')\\n }\\n\\n actOnMessage(event.data)\\n})\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_message_handler_origin", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 9, - "end": 11, - "column": { - "start": 1, - "end": 3 - } - }, - "sink": { - "start": 9, - "end": 11, - "column": { - "start": 1, - "end": 3 - }, - "content": "addEventListener('message', function f(event) {\\n actOnMessage(event.data)\\n})" - }, - "parent_line_number": 9, - "snippet": "addEventListener('message', function f(event) {\\n actOnMessage(event.data)\\n})", - "fingerprint": "4ac5e012a055ff87b9c6ec59be0139aa_2", - "old_fingerprint": "a8447e4b3d7e807590f9509e24e4470b_2", - "code_extract": "addEventListener('message', function f(event) {\\n actOnMessage(event.data)\\n})" - } - ] -}" -`; - -exports[`javascript_lang_message_handler_origin ok 1`] = `"{}"`; diff --git a/tests/javascript/lang/message_handler_origin/test.js b/tests/javascript/lang/message_handler_origin/test.js index fa284d13a..fc42999a0 100644 --- a/tests/javascript/lang/message_handler_origin/test.js +++ b/tests/javascript/lang/message_handler_origin/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.js" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/message_handler_origin/testdata/bad.js b/tests/javascript/lang/message_handler_origin/testdata/bad.js index 185f4b8b3..e26e191e3 100644 --- a/tests/javascript/lang/message_handler_origin/testdata/bad.js +++ b/tests/javascript/lang/message_handler_origin/testdata/bad.js @@ -1,11 +1,14 @@ +// bearer:expected javascript_lang_message_handler_origin window.addEventListener('message', (event) => { actOnMessage(event.data) }) +// bearer:expected javascript_lang_message_handler_origin addEventListener('message', function (event) { actOnMessage(event.data) }) +// bearer:expected javascript_lang_message_handler_origin addEventListener('message', function f(event) { actOnMessage(event.data) }) diff --git a/tests/javascript/lang/open_redirect/__snapshots__/test.js.snap b/tests/javascript/lang/open_redirect/__snapshots__/test.js.snap deleted file mode 100644 index dfa3648a5..000000000 --- a/tests/javascript/lang/open_redirect/__snapshots__/test.js.snap +++ /dev/null @@ -1,78 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_open_redirect insecure 1`] = ` -"{ - "medium": [ - { - "cwe_ids": [ - "601" - ], - "id": "javascript_lang_open_redirect", - "title": "Unsanitized user input in HTML redirect", - "description": "## Description\\nA redirect using unsanitized user input is bad practice and puts your application at greater risk of phishing attacks.\\n\\n## Remediations\\n\\nAvoid using redirects and forwards.\\n\\n## Resources\\n- [OWASP open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_open_redirect", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 30 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 30 - }, - "content": "window.location.href = myPath" - }, - "parent_line_number": 4, - "snippet": "window.location.href = myPath", - "fingerprint": "8d8402d704b040f97680d9409acaf85b_0", - "old_fingerprint": "6185982856f4b96a6b55f9374804e8b9_0", - "code_extract": "window.location.href = myPath" - }, - { - "cwe_ids": [ - "601" - ], - "id": "javascript_lang_open_redirect", - "title": "Unsanitized user input in HTML redirect", - "description": "## Description\\nA redirect using unsanitized user input is bad practice and puts your application at greater risk of phishing attacks.\\n\\n## Remediations\\n\\nAvoid using redirects and forwards.\\n\\n## Resources\\n- [OWASP open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_open_redirect", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 24 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 24 - }, - "content": "location.href = myPath2" - }, - "parent_line_number": 5, - "snippet": "location.href = myPath2", - "fingerprint": "8d8402d704b040f97680d9409acaf85b_1", - "old_fingerprint": "6185982856f4b96a6b55f9374804e8b9_1", - "code_extract": "location.href = myPath2" - } - ] -}" -`; - -exports[`javascript_lang_open_redirect secure 1`] = `"{}"`; diff --git a/tests/javascript/lang/open_redirect/test.js b/tests/javascript/lang/open_redirect/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/lang/open_redirect/test.js +++ b/tests/javascript/lang/open_redirect/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/open_redirect/testdata/insecure.js b/tests/javascript/lang/open_redirect/testdata/insecure.js index 39d7cf33c..d9ea4e72c 100644 --- a/tests/javascript/lang/open_redirect/testdata/insecure.js +++ b/tests/javascript/lang/open_redirect/testdata/insecure.js @@ -1,5 +1,7 @@ var myPath = new URLSearchParams(window.location) var myPath2 = new URL(location.href) +// bearer:expected javascript_lang_open_redirect window.location.href = myPath +// bearer:expected javascript_lang_open_redirect location.href = myPath2 diff --git a/tests/javascript/lang/os_command_injection/__snapshots__/test.js.snap b/tests/javascript/lang/os_command_injection/__snapshots__/test.js.snap deleted file mode 100644 index 308b7d91e..000000000 --- a/tests/javascript/lang/os_command_injection/__snapshots__/test.js.snap +++ /dev/null @@ -1,146 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_os_command_injection ok_no_os_command_injection 1`] = `"{}"`; - -exports[`javascript_lang_os_command_injection os_command_injection 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "78" - ], - "id": "javascript_lang_os_command_injection", - "title": "Unsanitized user input in OS command", - "description": "## Description\\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\\nThink twice if user input is really needed there.\\n\\nIt might be possible to use dynamic hardcoded values:\\n\\n\`\`\`javascript\\n let filePattern = \\"*.js\\"\\n\\n if req.params.graphql {\\n filePattern = \\"*.gql\\"\\n }\\n\\n cp.exec(\`cp \${filePattern} foo\`, (error, stdout, stderr) => {});\\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/javascript_lang_os_command_injection", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/os_command_injection.js", - "filename": ".", - "source": { - "start": 4, - "end": 6, - "column": { - "start": 3, - "end": 5 - } - }, - "sink": { - "start": 4, - "end": 6, - "column": { - "start": 3, - "end": 5 - }, - "content": "exec(\\"ls \\"+event[\\"user_dir\\"]+\\"| wc -l\\", (err, stdout, stderr) => {\\n // do something\\n })" - }, - "parent_line_number": 4, - "snippet": "exec(\\"ls \\"+event[\\"user_dir\\"]+\\"| wc -l\\", (err, stdout, stderr) => {\\n // do something\\n })", - "fingerprint": "b13e40973c5519829a310b6c100f0710_0", - "old_fingerprint": "cf9919163361d9a9aafa0a4bf6b67464_0", - "code_extract": " exec(\\"ls \\"+event[\\"user_dir\\"]+\\"| wc -l\\", (err, stdout, stderr) => {\\n // do something\\n });" - }, - { - "cwe_ids": [ - "78" - ], - "id": "javascript_lang_os_command_injection", - "title": "Unsanitized user input in OS command", - "description": "## Description\\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\\nThink twice if user input is really needed there.\\n\\nIt might be possible to use dynamic hardcoded values:\\n\\n\`\`\`javascript\\n let filePattern = \\"*.js\\"\\n\\n if req.params.graphql {\\n filePattern = \\"*.gql\\"\\n }\\n\\n cp.exec(\`cp \${filePattern} foo\`, (error, stdout, stderr) => {});\\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/javascript_lang_os_command_injection", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/os_command_injection.js", - "filename": ".", - "source": { - "start": 8, - "end": 10, - "column": { - "start": 3, - "end": 5 - } - }, - "sink": { - "start": 8, - "end": 10, - "column": { - "start": 3, - "end": 5 - }, - "content": "execSync(\\"ls \\"+event[\\"user\\"]+\\"| wc -l\\", (err, stdout, stderr) => {\\n // do something\\n })" - }, - "parent_line_number": 8, - "snippet": "execSync(\\"ls \\"+event[\\"user\\"]+\\"| wc -l\\", (err, stdout, stderr) => {\\n // do something\\n })", - "fingerprint": "b13e40973c5519829a310b6c100f0710_1", - "old_fingerprint": "cf9919163361d9a9aafa0a4bf6b67464_1", - "code_extract": " execSync(\\"ls \\"+event[\\"user\\"]+\\"| wc -l\\", (err, stdout, stderr) => {\\n // do something\\n });" - }, - { - "cwe_ids": [ - "78" - ], - "id": "javascript_lang_os_command_injection", - "title": "Unsanitized user input in OS command", - "description": "## Description\\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\\nThink twice if user input is really needed there.\\n\\nIt might be possible to use dynamic hardcoded values:\\n\\n\`\`\`javascript\\n let filePattern = \\"*.js\\"\\n\\n if req.params.graphql {\\n filePattern = \\"*.gql\\"\\n }\\n\\n cp.exec(\`cp \${filePattern} foo\`, (error, stdout, stderr) => {});\\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/javascript_lang_os_command_injection", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/os_command_injection.js", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 3, - "end": 24 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 3, - "end": 24 - }, - "content": "spawn(event[\\"query\\"])" - }, - "parent_line_number": 12, - "snippet": "spawn(event[\\"query\\"])", - "fingerprint": "b13e40973c5519829a310b6c100f0710_2", - "old_fingerprint": "cf9919163361d9a9aafa0a4bf6b67464_2", - "code_extract": " spawn(event[\\"query\\"]);" - }, - { - "cwe_ids": [ - "78" - ], - "id": "javascript_lang_os_command_injection", - "title": "Unsanitized user input in OS command", - "description": "## Description\\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\\nThink twice if user input is really needed there.\\n\\nIt might be possible to use dynamic hardcoded values:\\n\\n\`\`\`javascript\\n let filePattern = \\"*.js\\"\\n\\n if req.params.graphql {\\n filePattern = \\"*.gql\\"\\n }\\n\\n cp.exec(\`cp \${filePattern} foo\`, (error, stdout, stderr) => {});\\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/javascript_lang_os_command_injection", - "line_number": 14, - "full_filename": "/tmp/bearer-scan/os_command_injection.js", - "filename": ".", - "source": { - "start": 14, - "end": 14, - "column": { - "start": 3, - "end": 36 - } - }, - "sink": { - "start": 14, - "end": 14, - "column": { - "start": 3, - "end": 36 - }, - "content": "spawnSync(\\"grep \\" + event[\\"tmp\\"])" - }, - "parent_line_number": 14, - "snippet": "spawnSync(\\"grep \\" + event[\\"tmp\\"])", - "fingerprint": "b13e40973c5519829a310b6c100f0710_3", - "old_fingerprint": "cf9919163361d9a9aafa0a4bf6b67464_3", - "code_extract": " spawnSync(\\"grep \\" + event[\\"tmp\\"])" - } - ] -}" -`; diff --git a/tests/javascript/lang/os_command_injection/test.js b/tests/javascript/lang/os_command_injection/test.js index 03c68e696..82a452e11 100644 --- a/tests/javascript/lang/os_command_injection/test.js +++ b/tests/javascript/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("ok_no_os_command_injection", () => { + const testCase = "ok_no_os_command_injection.js" + + const results = invoke(testCase) - test("ok_no_os_command_injection", () => { - const testCase = "ok_no_os_command_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("os_command_injection", () => { - const testCase = "os_command_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("os_command_injection", () => { + const testCase = "os_command_injection.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/os_command_injection/testdata/os_command_injection.js b/tests/javascript/lang/os_command_injection/testdata/os_command_injection.js index 478e53802..28217210c 100644 --- a/tests/javascript/lang/os_command_injection/testdata/os_command_injection.js +++ b/tests/javascript/lang/os_command_injection/testdata/os_command_injection.js @@ -1,15 +1,19 @@ const { exec, execSync, spawn, spawnSync } = require('node:child_process'); exports.handler = async (event, _context) => { +// bearer:expected javascript_lang_os_command_injection exec("ls "+event["user_dir"]+"| wc -l", (err, stdout, stderr) => { // do something }); +// bearer:expected javascript_lang_os_command_injection execSync("ls "+event["user"]+"| wc -l", (err, stdout, stderr) => { // do something }); +// bearer:expected javascript_lang_os_command_injection spawn(event["query"]); +// bearer:expected javascript_lang_os_command_injection spawnSync("grep " + event["tmp"]) }; diff --git a/tests/javascript/lang/post_message_origin/__snapshots__/test.js.snap b/tests/javascript/lang/post_message_origin/__snapshots__/test.js.snap deleted file mode 100644 index 1d58912e8..000000000 --- a/tests/javascript/lang/post_message_origin/__snapshots__/test.js.snap +++ /dev/null @@ -1,78 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_post_message_origin bad 1`] = ` -"{ - "medium": [ - { - "cwe_ids": [ - "346" - ], - "id": "javascript_lang_post_message_origin", - "title": "Permissive origin in postMessage", - "description": "## Description\\n\\nUsing \\"*\\" (any) as the target origin of a postMessage call allows\\nthird-parties to read the message.\\n\\n## Remediations\\n\\n❌ Avoid using \\"*\\" as the target origin:\\n\\n\`\`\`javascript\\nwindow.postMessage(message, '*')\\n\`\`\`\\n\\n✅ Specify the origin for your target application:\\n\\n\`\`\`javascript\\nwindow.postMessage(message, 'https://myapp.example.com')\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_post_message_origin", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 26 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 26 - }, - "content": "postMessage(message, '*')" - }, - "parent_line_number": 1, - "snippet": "postMessage(message, '*')", - "fingerprint": "0e58e60389aa7b1dc2a5f244692f4333_0", - "old_fingerprint": "96ff67407e1715171bf80a8c1a6991e4_0", - "code_extract": "postMessage(message, '*')" - }, - { - "cwe_ids": [ - "346" - ], - "id": "javascript_lang_post_message_origin", - "title": "Permissive origin in postMessage", - "description": "## Description\\n\\nUsing \\"*\\" (any) as the target origin of a postMessage call allows\\nthird-parties to read the message.\\n\\n## Remediations\\n\\n❌ Avoid using \\"*\\" as the target origin:\\n\\n\`\`\`javascript\\nwindow.postMessage(message, '*')\\n\`\`\`\\n\\n✅ Specify the origin for your target application:\\n\\n\`\`\`javascript\\nwindow.postMessage(message, 'https://myapp.example.com')\\n\`\`\`\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_post_message_origin", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 33 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 33 - }, - "content": "window.postMessage(message, \\"*\\")" - }, - "parent_line_number": 3, - "snippet": "window.postMessage(message, \\"*\\")", - "fingerprint": "0e58e60389aa7b1dc2a5f244692f4333_1", - "old_fingerprint": "96ff67407e1715171bf80a8c1a6991e4_1", - "code_extract": "window.postMessage(message, \\"*\\")" - } - ] -}" -`; - -exports[`javascript_lang_post_message_origin ok 1`] = `"{}"`; diff --git a/tests/javascript/lang/post_message_origin/test.js b/tests/javascript/lang/post_message_origin/test.js index fa284d13a..fc42999a0 100644 --- a/tests/javascript/lang/post_message_origin/test.js +++ b/tests/javascript/lang/post_message_origin/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.js" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/post_message_origin/testdata/bad.js b/tests/javascript/lang/post_message_origin/testdata/bad.js index bb06d1aea..bef217705 100644 --- a/tests/javascript/lang/post_message_origin/testdata/bad.js +++ b/tests/javascript/lang/post_message_origin/testdata/bad.js @@ -1,3 +1,5 @@ +// bearer:expected javascript_lang_post_message_origin postMessage(message, '*') +// bearer:expected javascript_lang_post_message_origin window.postMessage(message, "*") diff --git a/tests/javascript/lang/raw_html_using_user_input/__snapshots__/test.js.snap b/tests/javascript/lang/raw_html_using_user_input/__snapshots__/test.js.snap deleted file mode 100644 index 1640945a2..000000000 --- a/tests/javascript/lang/raw_html_using_user_input/__snapshots__/test.js.snap +++ /dev/null @@ -1,656 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_raw_html_using_user_input bad 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 43 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 43 - }, - "content": "\`

    \${req.params.oops}

    \`" - }, - "parent_line_number": 1, - "snippet": "\`

    \${req.params.oops}

    \`", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_0", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_0", - "code_extract": "\`

    \${req.params.oops}

    \`" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 1, - "end": 30 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 1, - "end": 30 - }, - "content": "\`

    \${req.params.oops}

    \`" - }, - "parent_line_number": 2, - "snippet": "\`

    \${req.params.oops}

    \`", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_1", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_1", - "code_extract": "\`

    \${req.params.oops}

    \`" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 33 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 33 - }, - "content": "doT.compile(req.params.oops, {})" - }, - "parent_line_number": 4, - "snippet": "doT.compile(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_2", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_2", - "code_extract": "doT.compile(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 6, - "end": 6, - "column": { - "start": 1, - "end": 33 - } - }, - "sink": { - "start": 6, - "end": 6, - "column": { - "start": 1, - "end": 33 - }, - "content": "ejs.compile(req.params.oops, {})" - }, - "parent_line_number": 6, - "snippet": "ejs.compile(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_3", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_3", - "code_extract": "ejs.compile(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 8, - "end": 8, - "column": { - "start": 1, - "end": 40 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 1, - "end": 40 - }, - "content": "Handlebars.compile(req.params.oops, {})" - }, - "parent_line_number": 8, - "snippet": "Handlebars.compile(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_4", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_4", - "code_extract": "Handlebars.compile(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 1, - "end": 47 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 1, - "end": 47 - }, - "content": "Hogan.parse(Hogan.scan(req.params.oops), null)" - }, - "parent_line_number": 10, - "snippet": "Hogan.parse(Hogan.scan(req.params.oops), null)", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_5", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_5", - "code_extract": "Hogan.parse(Hogan.scan(req.params.oops), null)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 12, - "end": 12, - "column": { - "start": 1, - "end": 29 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 1, - "end": 29 - }, - "content": "$.templates(req.params.oops)" - }, - "parent_line_number": 12, - "snippet": "$.templates(req.params.oops)", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_6", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_6", - "code_extract": "$.templates(req.params.oops)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 14, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 14, - "end": 14, - "column": { - "start": 1, - "end": 30 - } - }, - "sink": { - "start": 14, - "end": 14, - "column": { - "start": 1, - "end": 30 - }, - "content": "template(req.params.oops, {})" - }, - "parent_line_number": 14, - "snippet": "template(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_7", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_7", - "code_extract": "template(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 15, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 15, - "end": 15, - "column": { - "start": 1, - "end": 32 - } - }, - "sink": { - "start": 15, - "end": 15, - "column": { - "start": 1, - "end": 32 - }, - "content": "_.template(req.params.oops, {})" - }, - "parent_line_number": 15, - "snippet": "_.template(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_8", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_8", - "code_extract": "_.template(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 17, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 17, - "end": 17, - "column": { - "start": 1, - "end": 49 - } - }, - "sink": { - "start": 17, - "end": 17, - "column": { - "start": 1, - "end": 49 - }, - "content": "compiler.compileSync(req.params.oops, \\"test.js\\")" - }, - "parent_line_number": 17, - "snippet": "compiler.compileSync(req.params.oops, \\"test.js\\")", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_9", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_9", - "code_extract": "compiler.compileSync(req.params.oops, \\"test.js\\")" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 19, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 19, - "end": 19, - "column": { - "start": 1, - "end": 37 - } - }, - "sink": { - "start": 19, - "end": 19, - "column": { - "start": 1, - "end": 37 - }, - "content": "Mustache.render(req.params.oops, {})" - }, - "parent_line_number": 19, - "snippet": "Mustache.render(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_10", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_10", - "code_extract": "Mustache.render(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 21, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 21, - "end": 21, - "column": { - "start": 1, - "end": 43 - } - }, - "sink": { - "start": 21, - "end": 21, - "column": { - "start": 1, - "end": 43 - }, - "content": "nunjucks.renderString(req.params.oops, {})" - }, - "parent_line_number": 21, - "snippet": "nunjucks.renderString(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_11", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_11", - "code_extract": "nunjucks.renderString(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 23, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 23, - "end": 23, - "column": { - "start": 1, - "end": 32 - } - }, - "sink": { - "start": 23, - "end": 23, - "column": { - "start": 1, - "end": 32 - }, - "content": "pug.render(req.params.oops, {})" - }, - "parent_line_number": 23, - "snippet": "pug.render(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_12", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_12", - "code_extract": "pug.render(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 25, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 25, - "end": 25, - "column": { - "start": 1, - "end": 33 - } - }, - "sink": { - "start": 25, - "end": 25, - "column": { - "start": 1, - "end": 33 - }, - "content": "Sqrl.render(req.params.oops, {})" - }, - "parent_line_number": 25, - "snippet": "Sqrl.render(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_13", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_13", - "code_extract": "Sqrl.render(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 27, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 27, - "end": 27, - "column": { - "start": 1, - "end": 39 - } - }, - "sink": { - "start": 27, - "end": 27, - "column": { - "start": 1, - "end": 39 - }, - "content": "Template7.compile(req.params.oops, {})" - }, - "parent_line_number": 27, - "snippet": "Template7.compile(req.params.oops, {})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_14", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_14", - "code_extract": "Template7.compile(req.params.oops, {})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 29, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 29, - "end": 35, - "column": { - "start": 1, - "end": 3 - } - }, - "sink": { - "start": 29, - "end": 35, - "column": { - "start": 1, - "end": 3 - }, - "content": "webix.ui({\\n id: \\"mylayout\\",\\n rows: [\\n { view: \\"toolbar\\", id: \\"mybar\\" },\\n { template: req.params.oops }\\n ]\\n})" - }, - "parent_line_number": 29, - "snippet": "webix.ui({\\n id: \\"mylayout\\",\\n rows: [\\n { view: \\"toolbar\\", id: \\"mybar\\" },\\n { template: req.params.oops }\\n ]\\n})", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_15", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_15", - "code_extract": "webix.ui({\\n id: \\"mylayout\\",\\n rows: [\\n ...omitted (buffer value 3)\\n { template: req.params.oops }\\n ]\\n})" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 44, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 44, - "end": 44, - "column": { - "start": 3, - "end": 47 - } - }, - "sink": { - "start": 44, - "end": 44, - "column": { - "start": 3, - "end": 47 - }, - "content": "Eta.render(req.params, { name: \\"insecure\\" })" - }, - "parent_line_number": 44, - "snippet": "Eta.render(req.params, { name: \\"insecure\\" })", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_16", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_16", - "code_extract": " Eta.render(req.params, { name: \\"insecure\\" })" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 51, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 51, - "end": 51, - "column": { - "start": 3, - "end": 44 - } - }, - "sink": { - "start": 51, - "end": 51, - "column": { - "start": 3, - "end": 44 - }, - "content": "whiskers.render(req.params.text, context)" - }, - "parent_line_number": 51, - "snippet": "whiskers.render(req.params.text, context)", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_17", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_17", - "code_extract": " whiskers.render(req.params.text, context)" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_lang_raw_html_using_user_input", - "title": "Unsanitized user input in raw HTML strings (XSS)", - "description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`javascript\\nconst html = \`

    \${req.params.title}

    \`\\n\`\`\`\\n\\n✅ Use a framework or templating language to construct the HTML.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`javascript\\nimport sanitizeHtml from 'sanitize-html'\\n\\nconst sanitizedTitle = sanitizeHtml(req.params.title)\\nconst html = \`

    \${sanitizedTitle}

    \`\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_raw_html_using_user_input", - "line_number": 58, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 58, - "end": 58, - "column": { - "start": 3, - "end": 52 - } - }, - "sink": { - "start": 58, - "end": 58, - "column": { - "start": 3, - "end": 52 - }, - "content": "engine.parse(req.params.text, { hello: \\"world\\" })" - }, - "parent_line_number": 58, - "snippet": "engine.parse(req.params.text, { hello: \\"world\\" })", - "fingerprint": "56d9a2a17ab908c88aee2b81bceff767_18", - "old_fingerprint": "c858f7f6f30bb28c6b1427458f7d3934_18", - "code_extract": " engine.parse(req.params.text, { hello: \\"world\\" })" - } - ] -}" -`; - -exports[`javascript_lang_raw_html_using_user_input ok 1`] = `"{}"`; diff --git a/tests/javascript/lang/raw_html_using_user_input/test.js b/tests/javascript/lang/raw_html_using_user_input/test.js index fa284d13a..fc42999a0 100644 --- a/tests/javascript/lang/raw_html_using_user_input/test.js +++ b/tests/javascript/lang/raw_html_using_user_input/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.js" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/raw_html_using_user_input/testdata/bad.js b/tests/javascript/lang/raw_html_using_user_input/testdata/bad.js index 0bcb10ede..1f95f105b 100644 --- a/tests/javascript/lang/raw_html_using_user_input/testdata/bad.js +++ b/tests/javascript/lang/raw_html_using_user_input/testdata/bad.js @@ -1,31 +1,47 @@ +// bearer:expected javascript_lang_raw_html_using_user_input `

    ${req.params.oops}

    ` +// bearer:expected javascript_lang_raw_html_using_user_input `

    ${req.params.oops}

    ` +// bearer:expected javascript_lang_raw_html_using_user_input doT.compile(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input ejs.compile(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input Handlebars.compile(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input Hogan.parse(Hogan.scan(req.params.oops), null) +// bearer:expected javascript_lang_raw_html_using_user_input $.templates(req.params.oops) +// bearer:expected javascript_lang_raw_html_using_user_input template(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input _.template(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input compiler.compileSync(req.params.oops, "test.js") +// bearer:expected javascript_lang_raw_html_using_user_input Mustache.render(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input nunjucks.renderString(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input pug.render(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input Sqrl.render(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input Template7.compile(req.params.oops, {}) +// bearer:expected javascript_lang_raw_html_using_user_input webix.ui({ id: "mylayout", rows: [ @@ -41,6 +57,7 @@ var app = express() import * as Eta from "eta"; app.get("/bad", (_req, _res) => { +// bearer:expected javascript_lang_raw_html_using_user_input Eta.render(req.params, { name: "insecure" }) }) @@ -48,6 +65,7 @@ app.get("/bad", (_req, _res) => { var whiskers = require("whiskers"); app.get("/bad", (req, _res) => { var context = {} +// bearer:expected javascript_lang_raw_html_using_user_input whiskers.render(req.params.text, context) }) @@ -55,5 +73,6 @@ app.get("/bad", (req, _res) => { import { Liquid } from 'liquidjs' const engine = new Liquid() app.get("/bad", (req, _res) => { +// bearer:expected javascript_lang_raw_html_using_user_input engine.parse(req.params.text, { hello: "world" }) }) diff --git a/tests/javascript/lang/regex_using_user_input/__snapshots__/test.js.snap b/tests/javascript/lang/regex_using_user_input/__snapshots__/test.js.snap deleted file mode 100644 index 5c6dc3997..000000000 --- a/tests/javascript/lang/regex_using_user_input/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_regex_using_user_input bad 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "1287" - ], - "id": "javascript_lang_regex_using_user_input", - "title": "Unsanitized user input in regular expression", - "description": "## Description\\n\\nApplications should avoid constructing regular expressions from user input.\\nRegular expressions can have exponential worst-case computational\\ncomplexity, allowing users to trigger this behaviour can result in\\nexcessive CPU consumption causing a regular expression denial of service (ReDoS).\\n\\n## Remediations\\n\\n❌ Avoid using untrusted or user data when building regular expressions\\n\\n## Resources\\n- [OWASP ReDoS attacks explained](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_regex_using_user_input", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 41 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 41 - }, - "content": "new RegExp(\`abc\${req.params.oops}\`, 'i')" - }, - "parent_line_number": 1, - "snippet": "new RegExp(\`abc\${req.params.oops}\`, 'i')", - "fingerprint": "042322614661c2cfbb59c697536202e3_0", - "old_fingerprint": "66dbf3e2c520e0f438bfcf2747cbfe29_0", - "code_extract": "new RegExp(\`abc\${req.params.oops}\`, 'i')" - } - ] -}" -`; - -exports[`javascript_lang_regex_using_user_input ok 1`] = `"{}"`; diff --git a/tests/javascript/lang/regex_using_user_input/test.js b/tests/javascript/lang/regex_using_user_input/test.js index fa284d13a..fc42999a0 100644 --- a/tests/javascript/lang/regex_using_user_input/test.js +++ b/tests/javascript/lang/regex_using_user_input/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.js" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/regex_using_user_input/testdata/bad.js b/tests/javascript/lang/regex_using_user_input/testdata/bad.js index 14af8e4a2..c7afbb0d6 100644 --- a/tests/javascript/lang/regex_using_user_input/testdata/bad.js +++ b/tests/javascript/lang/regex_using_user_input/testdata/bad.js @@ -1 +1,2 @@ +// bearer:expected javascript_lang_regex_using_user_input new RegExp(`abc${req.params.oops}`, 'i') diff --git a/tests/javascript/lang/session/__snapshots__/test.js.snap b/tests/javascript/lang/session/__snapshots__/test.js.snap deleted file mode 100644 index 8851cfb46..000000000 --- a/tests/javascript/lang/session/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_session not_session_leak 1`] = `"{}"`; - -exports[`javascript_lang_session session_leak 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "312" - ], - "id": "javascript_lang_session", - "title": "Leakage of sensitive data in local storage", - "description": "## Description\\n\\nSensitive data should not be stored in a \`localStorage\` session. This policy looks for any sensitive data stored within the localstorage.\\n\\n## Remediations\\n\\nIt's best to avoid storing sensitive data in \`localStorage\` whenever possible. To keep session data safe, use a server-based session storage solution instead.\\n\\n❌ If you do need do store data in \`localStorage\`, avoid including sensitive data:\\n\\n\`\`\`javascript\\nlocalStorage.setItem('user', email)\\n\`\`\`\\n\\n✅ Instead, use a unique identifier:\\n\\n\`\`\`javascript\\nlocalStorage.setItem('user', user.uuid)\\n\`\`\`\\n\\n## Resources\\n - [OWASP sensitive data exposure](https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_session", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/session_leak.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 1, - "end": 1, - "column": { - "start": 16, - "end": 28 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 35 - }, - "content": "localStorage.setItem(\\"user\\", user)" - }, - "parent_line_number": 3, - "snippet": "localStorage.setItem(\\"user\\", user)", - "fingerprint": "6c0cc3faaa947ecc7d7219e846383aa3_0", - "old_fingerprint": "09b466f85030d9662e55f4defe04fb42_0", - "code_extract": "localStorage.setItem(\\"user\\", user);" - } - ] -}" -`; diff --git a/tests/javascript/lang/session/test.js b/tests/javascript/lang/session/test.js index 4e0571a6f..e01a513f0 100644 --- a/tests/javascript/lang/session/test.js +++ b/tests/javascript/lang/session/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("not_session_leak", () => { + const testCase = "not_session_leak.js" + + const results = invoke(testCase) - test("not_session_leak", () => { - const testCase = "not_session_leak.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("session_leak", () => { - const testCase = "session_leak.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("session_leak", () => { + const testCase = "session_leak.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/session/testdata/session_leak.js b/tests/javascript/lang/session/testdata/session_leak.js index 29c8b7152..d4bcc7bf3 100644 --- a/tests/javascript/lang/session/testdata/session_leak.js +++ b/tests/javascript/lang/session/testdata/session_leak.js @@ -1,3 +1,4 @@ const user = { name: "jhon" }; +// bearer:expected javascript_lang_session localStorage.setItem("user", user); diff --git a/tests/javascript/lang/sql_injection/__snapshots__/test.js.snap b/tests/javascript/lang/sql_injection/__snapshots__/test.js.snap deleted file mode 100644 index a942ca400..000000000 --- a/tests/javascript/lang/sql_injection/__snapshots__/test.js.snap +++ /dev/null @@ -1,312 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_sql_injection knex_sql_injection 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "89" - ], - "id": "javascript_lang_sql_injection", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw SQL queries 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\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\"SELECT * FROM users WHERE ID = \\" + req.params.userId);\\n\`\`\`\\n\\nInstead, consider the following approaches when writing SQL queries\\n\\n✅ Validate query input wherever possible\\n\\n\`\`\`javascript\\n var rawId = req.params.userId\\n if !(/[0-9]+/.test(rawId)) {\\n // input is unexpected; don't make the query\\n }\\n\`\`\`\\n\\n✅ Use prepared (or parameterized) statements when querying\\n\\nSequelize example -\\n\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\n \\"SELECT * FROM users WHERE ID = ?\\",\\n { replacements: [req.params.userId] },\\n type: sequelize.QueryTypes.SELECT\\n )\\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/javascript_lang_sql_injection", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/knex_sql_injection.js", - "filename": ".", - "source": { - "start": 6, - "end": 9, - "column": { - "start": 20, - "end": 45 - } - }, - "sink": { - "start": 6, - "end": 9, - "column": { - "start": 20, - "end": 45 - }, - "content": "knex\\n\\t\\t.select(\\"user.cart_details\\")\\n\\t\\t.from(\\"users\\")\\n\\t\\t.whereRaw(\\"name = \\" + req.query.user.name)" - }, - "parent_line_number": 6, - "snippet": "knex\\n\\t\\t.select(\\"user.cart_details\\")\\n\\t\\t.from(\\"users\\")\\n\\t\\t.whereRaw(\\"name = \\" + req.query.user.name)", - "fingerprint": "e729d82176c9ebea695fa6b6a606960b_0", - "old_fingerprint": "880f4c9c37375e6b5f2109ca0c19d16d_0", - "code_extract": "\\tvar cartDetails = knex\\n\\t\\t.select(\\"user.cart_details\\")\\n\\t\\t.from(\\"users\\")\\n\\t\\t.whereRaw(\\"name = \\" + req.query.user.name);" - }, - { - "cwe_ids": [ - "89" - ], - "id": "javascript_lang_sql_injection", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw SQL queries 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\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\"SELECT * FROM users WHERE ID = \\" + req.params.userId);\\n\`\`\`\\n\\nInstead, consider the following approaches when writing SQL queries\\n\\n✅ Validate query input wherever possible\\n\\n\`\`\`javascript\\n var rawId = req.params.userId\\n if !(/[0-9]+/.test(rawId)) {\\n // input is unexpected; don't make the query\\n }\\n\`\`\`\\n\\n✅ Use prepared (or parameterized) statements when querying\\n\\nSequelize example -\\n\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\n \\"SELECT * FROM users WHERE ID = ?\\",\\n { replacements: [req.params.userId] },\\n type: sequelize.QueryTypes.SELECT\\n )\\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/javascript_lang_sql_injection", - "line_number": 15, - "full_filename": "/tmp/bearer-scan/knex_sql_injection.js", - "filename": ".", - "source": { - "start": 15, - "end": 17, - "column": { - "start": 20, - "end": 41 - } - }, - "sink": { - "start": 15, - "end": 17, - "column": { - "start": 20, - "end": 41 - }, - "content": "knex.select('user.cart_details')\\n\\t\\t.from('users')\\n\\t\\t.whereRaw('name = ' + event.user.name)" - }, - "parent_line_number": 15, - "snippet": "knex.select('user.cart_details')\\n\\t\\t.from('users')\\n\\t\\t.whereRaw('name = ' + event.user.name)", - "fingerprint": "e729d82176c9ebea695fa6b6a606960b_1", - "old_fingerprint": "880f4c9c37375e6b5f2109ca0c19d16d_1", - "code_extract": "\\tvar cartDetails = knex.select('user.cart_details')\\n\\t\\t.from('users')\\n\\t\\t.whereRaw('name = ' + event.user.name)" - } - ] -}" -`; - -exports[`javascript_lang_sql_injection mysql2_sql_injection 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "89" - ], - "id": "javascript_lang_sql_injection", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw SQL queries 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\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\"SELECT * FROM users WHERE ID = \\" + req.params.userId);\\n\`\`\`\\n\\nInstead, consider the following approaches when writing SQL queries\\n\\n✅ Validate query input wherever possible\\n\\n\`\`\`javascript\\n var rawId = req.params.userId\\n if !(/[0-9]+/.test(rawId)) {\\n // input is unexpected; don't make the query\\n }\\n\`\`\`\\n\\n✅ Use prepared (or parameterized) statements when querying\\n\\nSequelize example -\\n\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\n \\"SELECT * FROM users WHERE ID = ?\\",\\n { replacements: [req.params.userId] },\\n type: sequelize.QueryTypes.SELECT\\n )\\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/javascript_lang_sql_injection", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/mysql2_sql_injection.js", - "filename": ".", - "source": { - "start": 12, - "end": 14, - "column": { - "start": 2, - "end": 3 - } - }, - "sink": { - "start": 12, - "end": 14, - "column": { - "start": 2, - "end": 3 - }, - "content": "connection.query(\\n\\t\\t\\"SELECT * FROM \`user\` WHERE name = \\" + req.params.customer.name\\n\\t)" - }, - "parent_line_number": 12, - "snippet": "connection.query(\\n\\t\\t\\"SELECT * FROM \`user\` WHERE name = \\" + req.params.customer.name\\n\\t)", - "fingerprint": "e729d82176c9ebea695fa6b6a606960b_0", - "old_fingerprint": "e9eeaa250a67e5508b60f1fb3f8d50cc_0", - "code_extract": "\\tconnection.query(\\n\\t\\t\\"SELECT * FROM \`user\` WHERE name = \\" + req.params.customer.name\\n\\t);" - }, - { - "cwe_ids": [ - "89" - ], - "id": "javascript_lang_sql_injection", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw SQL queries 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\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\"SELECT * FROM users WHERE ID = \\" + req.params.userId);\\n\`\`\`\\n\\nInstead, consider the following approaches when writing SQL queries\\n\\n✅ Validate query input wherever possible\\n\\n\`\`\`javascript\\n var rawId = req.params.userId\\n if !(/[0-9]+/.test(rawId)) {\\n // input is unexpected; don't make the query\\n }\\n\`\`\`\\n\\n✅ Use prepared (or parameterized) statements when querying\\n\\nSequelize example -\\n\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\n \\"SELECT * FROM users WHERE ID = ?\\",\\n { replacements: [req.params.userId] },\\n type: sequelize.QueryTypes.SELECT\\n )\\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/javascript_lang_sql_injection", - "line_number": 18, - "full_filename": "/tmp/bearer-scan/mysql2_sql_injection.js", - "filename": ".", - "source": { - "start": 18, - "end": 21, - "column": { - "start": 2, - "end": 3 - } - }, - "sink": { - "start": 18, - "end": 21, - "column": { - "start": 2, - "end": 3 - }, - "content": "pool.query(\\n\\t\\t\\"SELECT * FROM users WHERE name = \\" + req.params.user_name,\\n\\t\\tfunction () {}\\n\\t)" - }, - "parent_line_number": 18, - "snippet": "pool.query(\\n\\t\\t\\"SELECT * FROM users WHERE name = \\" + req.params.user_name,\\n\\t\\tfunction () {}\\n\\t)", - "fingerprint": "e729d82176c9ebea695fa6b6a606960b_1", - "old_fingerprint": "e9eeaa250a67e5508b60f1fb3f8d50cc_1", - "code_extract": "\\tpool.query(\\n\\t\\t\\"SELECT * FROM users WHERE name = \\" + req.params.user_name,\\n\\t\\tfunction () {}\\n\\t);" - }, - { - "cwe_ids": [ - "89" - ], - "id": "javascript_lang_sql_injection", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw SQL queries 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\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\"SELECT * FROM users WHERE ID = \\" + req.params.userId);\\n\`\`\`\\n\\nInstead, consider the following approaches when writing SQL queries\\n\\n✅ Validate query input wherever possible\\n\\n\`\`\`javascript\\n var rawId = req.params.userId\\n if !(/[0-9]+/.test(rawId)) {\\n // input is unexpected; don't make the query\\n }\\n\`\`\`\\n\\n✅ Use prepared (or parameterized) statements when querying\\n\\nSequelize example -\\n\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\n \\"SELECT * FROM users WHERE ID = ?\\",\\n { replacements: [req.params.userId] },\\n type: sequelize.QueryTypes.SELECT\\n )\\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/javascript_lang_sql_injection", - "line_number": 23, - "full_filename": "/tmp/bearer-scan/mysql2_sql_injection.js", - "filename": ".", - "source": { - "start": 23, - "end": 23, - "column": { - "start": 3, - "end": 89 - } - }, - "sink": { - "start": 23, - "end": 23, - "column": { - "start": 3, - "end": 89 - }, - "content": "conn.query(\\"SELECT * FROM users WHERE name = \\" + req.params.user_name, function () {})" - }, - "parent_line_number": 23, - "snippet": "conn.query(\\"SELECT * FROM users WHERE name = \\" + req.params.user_name, function () {})", - "fingerprint": "e729d82176c9ebea695fa6b6a606960b_2", - "old_fingerprint": "e9eeaa250a67e5508b60f1fb3f8d50cc_2", - "code_extract": "\\t\\tconn.query(\\"SELECT * FROM users WHERE name = \\" + req.params.user_name, function () {});" - } - ] -}" -`; - -exports[`javascript_lang_sql_injection ok_no_sql_injection 1`] = `"{}"`; - -exports[`javascript_lang_sql_injection pg_sql_injection 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "89" - ], - "id": "javascript_lang_sql_injection", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw SQL queries 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\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\"SELECT * FROM users WHERE ID = \\" + req.params.userId);\\n\`\`\`\\n\\nInstead, consider the following approaches when writing SQL queries\\n\\n✅ Validate query input wherever possible\\n\\n\`\`\`javascript\\n var rawId = req.params.userId\\n if !(/[0-9]+/.test(rawId)) {\\n // input is unexpected; don't make the query\\n }\\n\`\`\`\\n\\n✅ Use prepared (or parameterized) statements when querying\\n\\nSequelize example -\\n\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\n \\"SELECT * FROM users WHERE ID = ?\\",\\n { replacements: [req.params.userId] },\\n type: sequelize.QueryTypes.SELECT\\n )\\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/javascript_lang_sql_injection", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/pg_sql_injection.js", - "filename": ".", - "source": { - "start": 8, - "end": 10, - "column": { - "start": 13, - "end": 3 - } - }, - "sink": { - "start": 8, - "end": 10, - "column": { - "start": 13, - "end": 3 - }, - "content": "client.query(\\n\\t\\t\\"SELECT * FROM users WHERE user.name = \\" + req.params.user.name\\n\\t)" - }, - "parent_line_number": 8, - "snippet": "client.query(\\n\\t\\t\\"SELECT * FROM users WHERE user.name = \\" + req.params.user.name\\n\\t)", - "fingerprint": "e729d82176c9ebea695fa6b6a606960b_0", - "old_fingerprint": "bc5d3f2f841878afc5a8115d2888f3a8_0", - "code_extract": "\\tvar user = client.query(\\n\\t\\t\\"SELECT * FROM users WHERE user.name = \\" + req.params.user.name\\n\\t);" - } - ] -}" -`; - -exports[`javascript_lang_sql_injection sequelize_sql_injection 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "89" - ], - "id": "javascript_lang_sql_injection", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw SQL queries 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\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\"SELECT * FROM users WHERE ID = \\" + req.params.userId);\\n\`\`\`\\n\\nInstead, consider the following approaches when writing SQL queries\\n\\n✅ Validate query input wherever possible\\n\\n\`\`\`javascript\\n var rawId = req.params.userId\\n if !(/[0-9]+/.test(rawId)) {\\n // input is unexpected; don't make the query\\n }\\n\`\`\`\\n\\n✅ Use prepared (or parameterized) statements when querying\\n\\nSequelize example -\\n\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\n \\"SELECT * FROM users WHERE ID = ?\\",\\n { replacements: [req.params.userId] },\\n type: sequelize.QueryTypes.SELECT\\n )\\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/javascript_lang_sql_injection", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/sequelize_sql_injection.js", - "filename": ".", - "source": { - "start": 7, - "end": 7, - "column": { - "start": 2, - "end": 29 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 2, - "end": 29 - }, - "content": "sqlite.query(customerQuery)" - }, - "parent_line_number": 7, - "snippet": "sqlite.query(customerQuery)", - "fingerprint": "e729d82176c9ebea695fa6b6a606960b_0", - "old_fingerprint": "f1d2ee2aa33151125a649885d538997b_0", - "code_extract": "\\tsqlite.query(customerQuery);" - } - ] -}" -`; - -exports[`javascript_lang_sql_injection sql_injection_juice 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "89" - ], - "id": "javascript_lang_sql_injection", - "title": "Unsanitized user input in SQL query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw SQL queries 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\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\"SELECT * FROM users WHERE ID = \\" + req.params.userId);\\n\`\`\`\\n\\nInstead, consider the following approaches when writing SQL queries\\n\\n✅ Validate query input wherever possible\\n\\n\`\`\`javascript\\n var rawId = req.params.userId\\n if !(/[0-9]+/.test(rawId)) {\\n // input is unexpected; don't make the query\\n }\\n\`\`\`\\n\\n✅ Use prepared (or parameterized) statements when querying\\n\\nSequelize example -\\n\`\`\`javascript\\n var sqlite = new Sequelize(\\"sqlite::memory:\\");\\n sqlite.query(\\n \\"SELECT * FROM users WHERE ID = ?\\",\\n { replacements: [req.params.userId] },\\n type: sequelize.QueryTypes.SELECT\\n )\\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/javascript_lang_sql_injection", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/sql_injection_juice.js", - "filename": ".", - "source": { - "start": 4, - "end": 12, - "column": { - "start": 7, - "end": 10 - } - }, - "sink": { - "start": 4, - "end": 12, - "column": { - "start": 7, - "end": 10 - }, - "content": "models.sequelize\\n .query(\\n \`SELECT * FROM Users WHERE email = '\${\\n req.body.email || \\"\\"\\n }' AND password = '\${security.hash(\\n req.body.password || \\"\\"\\n )}' AND deletedAt IS NULL\`,\\n { model: UserModel, plain: true }\\n )" - }, - "parent_line_number": 4, - "snippet": "models.sequelize\\n .query(\\n \`SELECT * FROM Users WHERE email = '\${\\n req.body.email || \\"\\"\\n }' AND password = '\${security.hash(\\n req.body.password || \\"\\"\\n )}' AND deletedAt IS NULL\`,\\n { model: UserModel, plain: true }\\n )", - "fingerprint": "e729d82176c9ebea695fa6b6a606960b_0", - "old_fingerprint": "6d3311960dc20256573ff2fbab5a8b1e_0", - "code_extract": " models.sequelize\\n .query(\\n \`SELECT * FROM Users WHERE email = '\${\\n ...omitted (buffer value 3)\\n )}' AND deletedAt IS NULL\`,\\n { model: UserModel, plain: true }\\n )" - } - ] -}" -`; - -exports[`javascript_lang_sql_injection sql_injection_juice_safe 1`] = `"{}"`; diff --git a/tests/javascript/lang/sql_injection/test.js b/tests/javascript/lang/sql_injection/test.js index 29fa1c616..644bab9d8 100644 --- a/tests/javascript/lang/sql_injection/test.js +++ b/tests/javascript/lang/sql_injection/test.js @@ -1,49 +1,80 @@ -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("knex_sql_injection", () => { + const testCase = "knex_sql_injection.js" + + const results = invoke(testCase) - test("knex_sql_injection", () => { - const testCase = "knex_sql_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("mysql2_sql_injection", () => { - const testCase = "mysql2_sql_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("mysql2_sql_injection", () => { + const testCase = "mysql2_sql_injection.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_no_sql_injection", () => { - const testCase = "ok_no_sql_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_no_sql_injection", () => { + const testCase = "ok_no_sql_injection.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("pg_sql_injection", () => { - const testCase = "pg_sql_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("pg_sql_injection", () => { + const testCase = "pg_sql_injection.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("sequelize_sql_injection", () => { - const testCase = "sequelize_sql_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("sequelize_sql_injection", () => { + const testCase = "sequelize_sql_injection.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("sql_injection_juice", () => { - const testCase = "sql_injection_juice.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("sql_injection_juice", () => { + const testCase = "sql_injection_juice.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("sql_injection_juice_safe", () => { - const testCase = "sql_injection_juice_safe.ts" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("sql_injection_juice_safe", () => { + const testCase = "sql_injection_juice_safe.ts" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/sql_injection/testdata/knex_sql_injection.js b/tests/javascript/lang/sql_injection/testdata/knex_sql_injection.js index 1d411f754..72d0f47f6 100644 --- a/tests/javascript/lang/sql_injection/testdata/knex_sql_injection.js +++ b/tests/javascript/lang/sql_injection/testdata/knex_sql_injection.js @@ -3,6 +3,7 @@ const knex = require("knex")({ }); module.exports.badQuery = function (req, res) { +// bearer:expected javascript_lang_sql_injection var cartDetails = knex .select("user.cart_details") .from("users") @@ -12,6 +13,7 @@ module.exports.badQuery = function (req, res) { }; exports.handler = async function (event, _context) { +// bearer:expected javascript_lang_sql_injection var cartDetails = knex.select('user.cart_details') .from('users') .whereRaw('name = ' + event.user.name) diff --git a/tests/javascript/lang/sql_injection/testdata/mysql2_sql_injection.js b/tests/javascript/lang/sql_injection/testdata/mysql2_sql_injection.js index 38ab893b1..580de3545 100644 --- a/tests/javascript/lang/sql_injection/testdata/mysql2_sql_injection.js +++ b/tests/javascript/lang/sql_injection/testdata/mysql2_sql_injection.js @@ -9,17 +9,20 @@ module.exports.asyncFooBar = async function (req, res) { }; module.exports.fooBar = function (req, _res) { +// bearer:expected javascript_lang_sql_injection connection.query( "SELECT * FROM `user` WHERE name = " + req.params.customer.name ); // pool query var pool = mysql.createPool(); +// bearer:expected javascript_lang_sql_injection pool.query( "SELECT * FROM users WHERE name = " + req.params.user_name, function () {} ); pool.getConnection(function (_err, conn) { +// bearer:expected javascript_lang_sql_injection conn.query("SELECT * FROM users WHERE name = " + req.params.user_name, function () {}); pool.releaseConnection(conn); }); diff --git a/tests/javascript/lang/sql_injection/testdata/pg_sql_injection.js b/tests/javascript/lang/sql_injection/testdata/pg_sql_injection.js index 1238f6eba..9040afb23 100644 --- a/tests/javascript/lang/sql_injection/testdata/pg_sql_injection.js +++ b/tests/javascript/lang/sql_injection/testdata/pg_sql_injection.js @@ -5,6 +5,7 @@ const client = new Client({ }); module.exports.fooBar = function (req, _res) { +// bearer:expected javascript_lang_sql_injection var user = client.query( "SELECT * FROM users WHERE user.name = " + req.params.user.name ); diff --git a/tests/javascript/lang/sql_injection/testdata/sequelize_sql_injection.js b/tests/javascript/lang/sql_injection/testdata/sequelize_sql_injection.js index 1b735f256..2f6fc153c 100644 --- a/tests/javascript/lang/sql_injection/testdata/sequelize_sql_injection.js +++ b/tests/javascript/lang/sql_injection/testdata/sequelize_sql_injection.js @@ -4,5 +4,6 @@ module.exports.fooBar = function (req, _res) { var sqlite = new Sequelize("sqlite::memory:"); var customerQuery = "SELECT * FROM customers WHERE status = " + req.params.customer.status; +// bearer:expected javascript_lang_sql_injection sqlite.query(customerQuery); }; diff --git a/tests/javascript/lang/sql_injection/testdata/sql_injection_juice.js b/tests/javascript/lang/sql_injection/testdata/sql_injection_juice.js index 2b9a1685f..65458f917 100644 --- a/tests/javascript/lang/sql_injection/testdata/sql_injection_juice.js +++ b/tests/javascript/lang/sql_injection/testdata/sql_injection_juice.js @@ -1,6 +1,7 @@ module.exports = function login() { function afterLogin(user, res, next) { return (req, _res, next) => { +// bearer:expected javascript_lang_sql_injection models.sequelize .query( `SELECT * FROM Users WHERE email = '${ diff --git a/tests/javascript/lang/weak_encryption_des/__snapshots__/test.js.snap b/tests/javascript/lang/weak_encryption_des/__snapshots__/test.js.snap deleted file mode 100644 index b9fb57bcd..000000000 --- a/tests/javascript/lang/weak_encryption_des/__snapshots__/test.js.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_weak_encryption_des des 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "327" - ], - "id": "javascript_lang_weak_encryption_des", - "title": "Usage of weak encryption algorithm (DES)", - "description": "## Description\\n\\nA weak encryption 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), DES (Data Encryption Standard) is considered a weak encryption algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger encryption algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst cipher = crypto.createCipheriv(\\"aes-256-cbc\\", key, iv);\\n\\nconst encrypted = cipher.update(\\"my secret message\\", \\"utf8\\");\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_encryption", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/des.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 33, - "end": 43 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 12, - "end": 58 - }, - "content": "CryptoJS.DES.encrypt(user.email, \\"secret key\\")" - }, - "parent_line_number": 3, - "snippet": "CryptoJS.DES.encrypt(user.email, \\"secret key\\")", - "fingerprint": "da1f702862f0e3603c21d0f8853815ab_0", - "old_fingerprint": "9542bc17e92b2c65731d651ccbbc7f08_0", - "code_extract": "var hash = CryptoJS.DES.encrypt(user.email, \\"secret key\\");" - } - ] -}" -`; diff --git a/tests/javascript/lang/weak_encryption_des/test.js b/tests/javascript/lang/weak_encryption_des/test.js index b81112444..3e2311112 100644 --- a/tests/javascript/lang/weak_encryption_des/test.js +++ b/tests/javascript/lang/weak_encryption_des/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("des", () => { + const testCase = "des.js" - test("des", () => { - const testCase = "des.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + const results = invoke(testCase) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + }) \ No newline at end of file diff --git a/tests/javascript/lang/weak_encryption_des/testdata/des.js b/tests/javascript/lang/weak_encryption_des/testdata/des.js index deed5455e..df49efb33 100644 --- a/tests/javascript/lang/weak_encryption_des/testdata/des.js +++ b/tests/javascript/lang/weak_encryption_des/testdata/des.js @@ -1,3 +1,4 @@ import { CryptoJS } from "crypto-js" +// bearer:expected javascript_lang_weak_encryption_des var hash = CryptoJS.DES.encrypt(user.email, "secret key"); diff --git a/tests/javascript/lang/weak_encryption_rc4/__snapshots__/test.js.snap b/tests/javascript/lang/weak_encryption_rc4/__snapshots__/test.js.snap deleted file mode 100644 index 13636cf91..000000000 --- a/tests/javascript/lang/weak_encryption_rc4/__snapshots__/test.js.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_weak_encryption_rc4 rc4 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "327" - ], - "id": "javascript_lang_weak_encryption_rc4", - "title": "Usage of weak encryption algorithm (RC4)", - "description": "## Description\\n\\nA weak encryption 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), RC4 (Rivest Cipher 4) is considered a weak encryption algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger encryption algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst cipher = crypto.createCipheriv(\\"aes-256-cbc\\", key, iv);\\n\\nconst encrypted = cipher.update(\\"my secret message\\", \\"utf8\\");\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_encryption_rc4", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/rc4.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 22, - "end": 32 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 47 - }, - "content": "CryptoJS.RC4.encrypt(user.email, \\"secret key\\")" - }, - "parent_line_number": 3, - "snippet": "CryptoJS.RC4.encrypt(user.email, \\"secret key\\")", - "fingerprint": "b7095893a4df6379250dd8d32db44880_0", - "old_fingerprint": "fc184834779816acc9558b565162e417_0", - "code_extract": "CryptoJS.RC4.encrypt(user.email, \\"secret key\\");" - } - ] -}" -`; diff --git a/tests/javascript/lang/weak_encryption_rc4/test.js b/tests/javascript/lang/weak_encryption_rc4/test.js index 5e442e916..e0f1f8f72 100644 --- a/tests/javascript/lang/weak_encryption_rc4/test.js +++ b/tests/javascript/lang/weak_encryption_rc4/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("rc4", () => { + const testCase = "rc4.js" + + const results = invoke(testCase) - test("rc4", () => { - const testCase = "rc4.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/weak_encryption_rc4/testdata/rc4.js b/tests/javascript/lang/weak_encryption_rc4/testdata/rc4.js index bc29a7528..ab6d36095 100644 --- a/tests/javascript/lang/weak_encryption_rc4/testdata/rc4.js +++ b/tests/javascript/lang/weak_encryption_rc4/testdata/rc4.js @@ -1,3 +1,4 @@ import { CryptoJS } from "crypto-js" +// bearer:expected javascript_lang_weak_encryption_rc4 CryptoJS.RC4.encrypt(user.email, "secret key"); diff --git a/tests/javascript/lang/weak_hash_md5/__snapshots__/test.js.snap b/tests/javascript/lang/weak_hash_md5/__snapshots__/test.js.snap deleted file mode 100644 index c311af416..000000000 --- a/tests/javascript/lang/weak_hash_md5/__snapshots__/test.js.snap +++ /dev/null @@ -1,226 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_weak_hash_md5 crypto_md5 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "328" - ], - "id": "javascript_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 hash algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger hashing algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst key = \\"secret key\\";\\nconst hash = crypto.createHmac(\\"es-256-cbc\\", key).update(user.password);\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_hash_md5", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/crypto_md5.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 4, - "end": 4, - "column": { - "start": 40, - "end": 50 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 51 - }, - "content": "myCrypto.createHmac(\\"md5\\", key).update(user.email)" - }, - "parent_line_number": 4, - "snippet": "myCrypto.createHmac(\\"md5\\", key).update(user.email)", - "fingerprint": "c4f165d7f589bd4f3415165e96c2b249_0", - "old_fingerprint": "5f7ffe7da12bab4459cdb44a8be8ba08_0", - "code_extract": "myCrypto.createHmac(\\"md5\\", key).update(user.email);" - }, - { - "cwe_ids": [ - "328" - ], - "id": "javascript_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 hash algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger hashing algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst key = \\"secret key\\";\\nconst hash = crypto.createHmac(\\"es-256-cbc\\", key).update(user.password);\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_hash_md5", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/crypto_md5.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 49, - "end": 59 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 15, - "end": 60 - }, - "content": "myCrypto.createHash(\\"md5\\").update(user.email)" - }, - "parent_line_number": 5, - "snippet": "myCrypto.createHash(\\"md5\\").update(user.email)", - "fingerprint": "c4f165d7f589bd4f3415165e96c2b249_1", - "old_fingerprint": "5f7ffe7da12bab4459cdb44a8be8ba08_1", - "code_extract": "var hashmd5 = myCrypto.createHash(\\"md5\\").update(user.email);" - } - ] -}" -`; - -exports[`javascript_lang_weak_hash_md5 cryptojs_md5 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "328" - ], - "id": "javascript_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 hash algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger hashing algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst key = \\"secret key\\";\\nconst hash = crypto.createHmac(\\"es-256-cbc\\", key).update(user.password);\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_hash_md5", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/cryptojs_md5.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 2, - "end": 2, - "column": { - "start": 27, - "end": 37 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 12, - "end": 38 - }, - "content": "MyCryptoJS.MD5(user.email)" - }, - "parent_line_number": 2, - "snippet": "MyCryptoJS.MD5(user.email)", - "fingerprint": "c4f165d7f589bd4f3415165e96c2b249_0", - "old_fingerprint": "c51ec588c3a82750a8a435bfa0d6da1a_0", - "code_extract": "var hash = MyCryptoJS.MD5(user.email);" - } - ] -}" -`; - -exports[`javascript_lang_weak_hash_md5 md5 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "328" - ], - "id": "javascript_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 hash algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger hashing algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst key = \\"secret key\\";\\nconst hash = crypto.createHmac(\\"es-256-cbc\\", key).update(user.password);\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_hash_md5", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/md5.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 4, - "end": 4, - "column": { - "start": 20, - "end": 35 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 14, - "end": 36 - }, - "content": "myMd5(req.query.email)" - }, - "parent_line_number": 4, - "snippet": "myMd5(req.query.email)", - "fingerprint": "c4f165d7f589bd4f3415165e96c2b249_0", - "old_fingerprint": "92bff4755c0c3a39ad0f98e5a35ed1d5_0", - "code_extract": " hashedPw = myMd5(req.query.email)" - } - ], - "high": [ - { - "cwe_ids": [ - "328" - ], - "id": "javascript_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 hash algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger hashing algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst key = \\"secret key\\";\\nconst hash = crypto.createHmac(\\"es-256-cbc\\", key).update(user.password);\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_hash_md5", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/md5.js", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 14, - "end": 28 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 14, - "end": 28 - }, - "content": "myMd5(\\"hello\\")" - }, - "parent_line_number": 5, - "snippet": "myMd5(\\"hello\\")", - "fingerprint": "c4f165d7f589bd4f3415165e96c2b249_1", - "old_fingerprint": "92bff4755c0c3a39ad0f98e5a35ed1d5_1", - "code_extract": " hashedPw = myMd5(\\"hello\\")" - } - ] -}" -`; diff --git a/tests/javascript/lang/weak_hash_md5/test.js b/tests/javascript/lang/weak_hash_md5/test.js index b82a582d7..0169eee7a 100644 --- a/tests/javascript/lang/weak_hash_md5/test.js +++ b/tests/javascript/lang/weak_hash_md5/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("crypto_md5", () => { + const testCase = "crypto_md5.js" + + const results = invoke(testCase) - test("crypto_md5", () => { - const testCase = "crypto_md5.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("cryptojs_md5", () => { - const testCase = "cryptojs_md5.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("cryptojs_md5", () => { + const testCase = "cryptojs_md5.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("md5", () => { - const testCase = "md5.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("md5", () => { + const testCase = "md5.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/weak_hash_md5/testdata/crypto_md5.js b/tests/javascript/lang/weak_hash_md5/testdata/crypto_md5.js index 889f9dc83..85d686edd 100644 --- a/tests/javascript/lang/weak_hash_md5/testdata/crypto_md5.js +++ b/tests/javascript/lang/weak_hash_md5/testdata/crypto_md5.js @@ -1,5 +1,7 @@ const myCrypto = require("crypto") var key = "secret key"; +// bearer:expected javascript_lang_weak_hash_md5 myCrypto.createHmac("md5", key).update(user.email); +// bearer:expected javascript_lang_weak_hash_md5 var hashmd5 = myCrypto.createHash("md5").update(user.email); diff --git a/tests/javascript/lang/weak_hash_md5/testdata/cryptojs_md5.js b/tests/javascript/lang/weak_hash_md5/testdata/cryptojs_md5.js index 1115cb515..ee65d13c3 100644 --- a/tests/javascript/lang/weak_hash_md5/testdata/cryptojs_md5.js +++ b/tests/javascript/lang/weak_hash_md5/testdata/cryptojs_md5.js @@ -1,2 +1,3 @@ import * as MyCryptoJS from "crypto-js" +// bearer:expected javascript_lang_weak_hash_md5 var hash = MyCryptoJS.MD5(user.email); diff --git a/tests/javascript/lang/weak_hash_md5/testdata/md5.js b/tests/javascript/lang/weak_hash_md5/testdata/md5.js index 86b0c77a4..29db718a7 100644 --- a/tests/javascript/lang/weak_hash_md5/testdata/md5.js +++ b/tests/javascript/lang/weak_hash_md5/testdata/md5.js @@ -1,6 +1,8 @@ const myMd5 = require("md5") module.exports.hashPw = function (req, _res) { +// bearer:expected javascript_lang_weak_hash_md5 hashedPw = myMd5(req.query.email) +// bearer:expected javascript_lang_weak_hash_md5 hashedPw = myMd5("hello") } \ No newline at end of file diff --git a/tests/javascript/lang/weak_hash_sha1/__snapshots__/test.js.snap b/tests/javascript/lang/weak_hash_sha1/__snapshots__/test.js.snap deleted file mode 100644 index 688133d46..000000000 --- a/tests/javascript/lang/weak_hash_sha1/__snapshots__/test.js.snap +++ /dev/null @@ -1,178 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_weak_hash_sha1 secure 1`] = `"{}"`; - -exports[`javascript_lang_weak_hash_sha1 sha1 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "328" - ], - "id": "javascript_lang_weak_hash_sha1", - "title": "Usage of weak hashing library (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 hash algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger hashing algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst key = \\"secret key\\";\\nconst hash = crypto.createHmac(\\"es-256-cbc\\", key).update(user.password);\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_hash_sha1", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/sha1.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 57, - "end": 67 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 17, - "end": 68 - }, - "content": "myCrypto.createHmac(\\"sha1\\", key).update(user.email)" - }, - "parent_line_number": 5, - "snippet": "myCrypto.createHmac(\\"sha1\\", key).update(user.email)", - "fingerprint": "68b0e05340dc0b05a89f0a0753374255_0", - "old_fingerprint": "38ca7a09d253090085cb0ae595105fe5_0", - "code_extract": "var encrypted = myCrypto.createHmac(\\"sha1\\", key).update(user.email);" - }, - { - "cwe_ids": [ - "328" - ], - "id": "javascript_lang_weak_hash_sha1", - "title": "Usage of weak hashing library (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 hash algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger hashing algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst key = \\"secret key\\";\\nconst hash = crypto.createHmac(\\"es-256-cbc\\", key).update(user.password);\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_hash_sha1", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/sha1.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 6, - "end": 6, - "column": { - "start": 50, - "end": 60 - } - }, - "sink": { - "start": 6, - "end": 6, - "column": { - "start": 15, - "end": 61 - }, - "content": "myCrypto.createHash(\\"sha1\\").update(user.email)" - }, - "parent_line_number": 6, - "snippet": "myCrypto.createHash(\\"sha1\\").update(user.email)", - "fingerprint": "68b0e05340dc0b05a89f0a0753374255_1", - "old_fingerprint": "38ca7a09d253090085cb0ae595105fe5_1", - "code_extract": "var hashmd5 = myCrypto.createHash(\\"sha1\\").update(user.email);" - }, - { - "cwe_ids": [ - "328" - ], - "id": "javascript_lang_weak_hash_sha1", - "title": "Usage of weak hashing library (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 hash algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger hashing algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst key = \\"secret key\\";\\nconst hash = crypto.createHmac(\\"es-256-cbc\\", key).update(user.password);\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_hash_sha1", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/sha1.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 8, - "end": 8, - "column": { - "start": 21, - "end": 31 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 1, - "end": 39 - }, - "content": "MyCryptoJS.HmacSHA1(user.email, \\"Key\\")" - }, - "parent_line_number": 8, - "snippet": "MyCryptoJS.HmacSHA1(user.email, \\"Key\\")", - "fingerprint": "68b0e05340dc0b05a89f0a0753374255_2", - "old_fingerprint": "38ca7a09d253090085cb0ae595105fe5_2", - "code_extract": "MyCryptoJS.HmacSHA1(user.email, \\"Key\\")" - }, - { - "cwe_ids": [ - "328" - ], - "id": "javascript_lang_weak_hash_sha1", - "title": "Usage of weak hashing library (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 hash algorithm and therefore shouldn't be used.\\n\\n✅ Use stronger hashing algorithms when storing data.\\n\\n\`\`\`javascript\\nconst crypto = require(\\"crypto\\");\\n\\nconst key = \\"secret key\\";\\nconst hash = crypto.createHmac(\\"es-256-cbc\\", key).update(user.password);\\n\`\`\`\\n\\n## Resources\\n- [NodeJS Crypto Module](https://nodejs.org/api/crypto.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_hash_sha1", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/sha1.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 9, - "end": 9, - "column": { - "start": 17, - "end": 27 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 1, - "end": 28 - }, - "content": "MyCryptoJS.SHA1(user.email)" - }, - "parent_line_number": 9, - "snippet": "MyCryptoJS.SHA1(user.email)", - "fingerprint": "68b0e05340dc0b05a89f0a0753374255_3", - "old_fingerprint": "38ca7a09d253090085cb0ae595105fe5_3", - "code_extract": "MyCryptoJS.SHA1(user.email)" - } - ] -}" -`; diff --git a/tests/javascript/lang/weak_hash_sha1/test.js b/tests/javascript/lang/weak_hash_sha1/test.js index 41f8f351a..b7c37c5b3 100644 --- a/tests/javascript/lang/weak_hash_sha1/test.js +++ b/tests/javascript/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("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("sha1", () => { - const testCase = "sha1.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("sha1", () => { + const testCase = "sha1.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/weak_hash_sha1/testdata/sha1.js b/tests/javascript/lang/weak_hash_sha1/testdata/sha1.js index 04cb9a7d6..5560e4403 100644 --- a/tests/javascript/lang/weak_hash_sha1/testdata/sha1.js +++ b/tests/javascript/lang/weak_hash_sha1/testdata/sha1.js @@ -2,8 +2,12 @@ import MyCryptoJS from "crypto-js" const myCrypto = require("crypto") var key = "secret key"; +// bearer:expected javascript_lang_weak_hash_sha1 var encrypted = myCrypto.createHmac("sha1", key).update(user.email); +// bearer:expected javascript_lang_weak_hash_sha1 var hashmd5 = myCrypto.createHash("sha1").update(user.email); +// bearer:expected javascript_lang_weak_hash_sha1 MyCryptoJS.HmacSHA1(user.email, "Key") +// bearer:expected javascript_lang_weak_hash_sha1 MyCryptoJS.SHA1(user.email) diff --git a/tests/javascript/lang/weak_password_encryption_des/__snapshots__/test.js.snap b/tests/javascript/lang/weak_password_encryption_des/__snapshots__/test.js.snap deleted file mode 100644 index 5eb2d6dc2..000000000 --- a/tests/javascript/lang/weak_password_encryption_des/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_weak_password_encryption_des des_password 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "326" - ], - "id": "javascript_lang_weak_password_encryption_des", - "title": "Usage of weak encryption algorithm on a password (DES)", - "description": "## Description\\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), DES (Data Encryption Standard) is considered a weak encryption algorithm and therefore shouldn't be used.\\n\\nMoreover, since encryption is reversible, it is possible to retrieve the plaintext value. This makes encryption a bad choice for passwords. Instead, passwords should be hashed.\\n\\n## Remediations\\n\\n❌ Do not use encryption for passwords, wherever possible.\\n\\n✅ Use a recommended hashing library such as Argon2id for passwords\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2id })\\n\`\`\`\\n\\n## Resources\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_encryption_des", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/des_password.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 22, - "end": 35 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 50 - }, - "content": "CryptoJS.DES.encrypt(user.password, \\"secret key\\")" - }, - "parent_line_number": 3, - "snippet": "CryptoJS.DES.encrypt(user.password, \\"secret key\\")", - "fingerprint": "5a44201c9c3986673d27c5e23a7d3d4d_0", - "old_fingerprint": "7c715caf1233d8fe5f17bca3902ca1b7_0", - "code_extract": "CryptoJS.DES.encrypt(user.password, \\"secret key\\");" - } - ] -}" -`; - -exports[`javascript_lang_weak_password_encryption_des ok_not_a_password 1`] = `"{}"`; diff --git a/tests/javascript/lang/weak_password_encryption_des/test.js b/tests/javascript/lang/weak_password_encryption_des/test.js index e15e4068e..3acb91db3 100644 --- a/tests/javascript/lang/weak_password_encryption_des/test.js +++ b/tests/javascript/lang/weak_password_encryption_des/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("des_password", () => { + const testCase = "des_password.js" + + const results = invoke(testCase) - test("des_password", () => { - const testCase = "des_password.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_not_a_password", () => { - const testCase = "ok_not_a_password.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_not_a_password", () => { + const testCase = "ok_not_a_password.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/weak_password_encryption_des/testdata/des_password.js b/tests/javascript/lang/weak_password_encryption_des/testdata/des_password.js index 82acbf960..dca42cddc 100644 --- a/tests/javascript/lang/weak_password_encryption_des/testdata/des_password.js +++ b/tests/javascript/lang/weak_password_encryption_des/testdata/des_password.js @@ -1,3 +1,4 @@ import { CryptoJS } from "crypto-js" +// bearer:expected javascript_lang_weak_password_encryption_des CryptoJS.DES.encrypt(user.password, "secret key"); diff --git a/tests/javascript/lang/weak_password_encryption_rc4/__snapshots__/test.js.snap b/tests/javascript/lang/weak_password_encryption_rc4/__snapshots__/test.js.snap deleted file mode 100644 index 42e272be0..000000000 --- a/tests/javascript/lang/weak_password_encryption_rc4/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_weak_password_encryption_rc4 ok_not_a_password 1`] = `"{}"`; - -exports[`javascript_lang_weak_password_encryption_rc4 rc4_password 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "326" - ], - "id": "javascript_lang_weak_password_encryption_rc4", - "title": "Usage of weak encryption algorithm on a password (RC4)", - "description": "## Description\\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), RC4 is considered a weak encryption algorithm and therefore shouldn't be used.\\n\\nMoreover, since encryption is reversible, it is possible to retrieve the plaintext value. This makes encryption a bad choice for passwords. Instead, passwords should be hashed.\\n\\n## Remediations\\n\\n❌ Do not use encryption for passwords, wherever possible.\\n\\n✅ Use a recommended hashing library such as Argon2id for passwords\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2id })\\n\`\`\`\\n\\n## Resources\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_encryption_rc4", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/rc4_password.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 33, - "end": 46 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 12, - "end": 61 - }, - "content": "CryptoJS.RC4.encrypt(user.password, \\"secret key\\")" - }, - "parent_line_number": 3, - "snippet": "CryptoJS.RC4.encrypt(user.password, \\"secret key\\")", - "fingerprint": "116301d7345859a7151ef3a9fc93dff2_0", - "old_fingerprint": "d3dd9c313c87e583d9ccc52571f67a41_0", - "code_extract": "var hash = CryptoJS.RC4.encrypt(user.password, \\"secret key\\");" - } - ] -}" -`; diff --git a/tests/javascript/lang/weak_password_encryption_rc4/test.js b/tests/javascript/lang/weak_password_encryption_rc4/test.js index e67fa50f5..06e45c076 100644 --- a/tests/javascript/lang/weak_password_encryption_rc4/test.js +++ b/tests/javascript/lang/weak_password_encryption_rc4/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.js" + + const results = invoke(testCase) - test("ok_not_a_password", () => { - const testCase = "ok_not_a_password.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("rc4_password", () => { - const testCase = "rc4_password.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("rc4_password", () => { + const testCase = "rc4_password.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/weak_password_encryption_rc4/testdata/rc4_password.js b/tests/javascript/lang/weak_password_encryption_rc4/testdata/rc4_password.js index a6a1c34a4..51d90f139 100644 --- a/tests/javascript/lang/weak_password_encryption_rc4/testdata/rc4_password.js +++ b/tests/javascript/lang/weak_password_encryption_rc4/testdata/rc4_password.js @@ -1,3 +1,4 @@ import { CryptoJS } from "crypto-js" +// bearer:expected javascript_lang_weak_password_encryption_rc4 var hash = CryptoJS.RC4.encrypt(user.password, "secret key"); diff --git a/tests/javascript/lang/weak_password_hash_argon2/__snapshots__/test.js.snap b/tests/javascript/lang/weak_password_hash_argon2/__snapshots__/test.js.snap deleted file mode 100644 index 7aae4f851..000000000 --- a/tests/javascript/lang/weak_password_hash_argon2/__snapshots__/test.js.snap +++ /dev/null @@ -1,54 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_weak_password_hash_argon2 argon2i 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "326" - ], - "id": "javascript_lang_weak_password_hash_argon2", - "title": "Usage of weak hashing library on a password (Argon2)", - "description": "## Description\\n\\nOut of the three variants of the Argon2 algorithm (Argon2i, Argon2d, Argon2id), Argon2id is the recommended choice because it offers the best protection.\\n\\n## Recommendations\\n\\n❌ Do not override the default type (Argon2id) when using the Argon2 library\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2i })\\n\`\`\`\\n\\n## Resources\\n- [Argon2 type options](https://github.com/ranisalt/node-argon2/wiki/Options#type)\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_hash_argon2", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/argon2i.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 4, - "end": 4, - "column": { - "start": 34, - "end": 54 - } - }, - "sink": { - "start": 4, - "end": 8, - "column": { - "start": 22, - "end": 5 - }, - "content": "argon2.hash(currentUser.password, {\\n type: argon2.argon2i,\\n memoryCost: 2 ** 16,\\n hashLength: 50,\\n })" - }, - "parent_line_number": 4, - "snippet": "argon2.hash(currentUser.password, {\\n type: argon2.argon2i,\\n memoryCost: 2 ** 16,\\n hashLength: 50,\\n })", - "fingerprint": "29037a4aa6dcbd49fb1b22d24d403754_0", - "old_fingerprint": "5c21523ad759096994916831a8bdca65_0", - "code_extract": " const hash = await argon2.hash(currentUser.password, {\\n type: argon2.argon2i,\\n memoryCost: 2 ** 16,\\n hashLength: 50,\\n });" - } - ] -}" -`; - -exports[`javascript_lang_weak_password_hash_argon2 ok_encryption 1`] = `"{}"`; - -exports[`javascript_lang_weak_password_hash_argon2 ok_not_a_password 1`] = `"{}"`; diff --git a/tests/javascript/lang/weak_password_hash_argon2/test.js b/tests/javascript/lang/weak_password_hash_argon2/test.js index 25a7ca239..2ffa4b4f0 100644 --- a/tests/javascript/lang/weak_password_hash_argon2/test.js +++ b/tests/javascript/lang/weak_password_hash_argon2/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("argon2i", () => { + const testCase = "argon2i.js" + + const results = invoke(testCase) - test("argon2i", () => { - const testCase = "argon2i.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_encryption", () => { - const testCase = "ok_encryption.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_encryption", () => { + const testCase = "ok_encryption.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_not_a_password", () => { - const testCase = "ok_not_a_password.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_not_a_password", () => { + const testCase = "ok_not_a_password.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/weak_password_hash_argon2/testdata/argon2i.js b/tests/javascript/lang/weak_password_hash_argon2/testdata/argon2i.js index 9fdbba2a3..fa6426cf4 100644 --- a/tests/javascript/lang/weak_password_hash_argon2/testdata/argon2i.js +++ b/tests/javascript/lang/weak_password_hash_argon2/testdata/argon2i.js @@ -1,6 +1,7 @@ const argon2 = require("argon2"); app.get("/bad", async (_req, res) => { +// bearer:expected javascript_lang_weak_password_hash_argon2 const hash = await argon2.hash(currentUser.password, { type: argon2.argon2i, memoryCost: 2 ** 16, diff --git a/tests/javascript/lang/weak_password_hash_md5/__snapshots__/test.js.snap b/tests/javascript/lang/weak_password_hash_md5/__snapshots__/test.js.snap deleted file mode 100644 index cbf7766a9..000000000 --- a/tests/javascript/lang/weak_password_hash_md5/__snapshots__/test.js.snap +++ /dev/null @@ -1,136 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_weak_password_hash_md5 md5_password 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "326" - ], - "id": "javascript_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\\n✅ Use a recommended hashing library such as Argon2id for passwords\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2id })\\n\`\`\`\\n\\n## Resources\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_hash_md5", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/md5_password.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 4, - "end": 4, - "column": { - "start": 54, - "end": 67 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 17, - "end": 68 - }, - "content": "crypto.createHmac(\\"md5\\", key).update(user.password)" - }, - "parent_line_number": 4, - "snippet": "crypto.createHmac(\\"md5\\", key).update(user.password)", - "fingerprint": "842bae8a65c472461b4845ea606a7fed_0", - "old_fingerprint": "29170146f7ca0a20898163aad42ffe78_0", - "code_extract": "var encrypted = crypto.createHmac(\\"md5\\", key).update(user.password);" - }, - { - "cwe_ids": [ - "326" - ], - "id": "javascript_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\\n✅ Use a recommended hashing library such as Argon2id for passwords\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2id })\\n\`\`\`\\n\\n## Resources\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_hash_md5", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/md5_password.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 47, - "end": 60 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 15, - "end": 61 - }, - "content": "crypto.createHash(\\"md5\\").update(user.password)" - }, - "parent_line_number": 5, - "snippet": "crypto.createHash(\\"md5\\").update(user.password)", - "fingerprint": "842bae8a65c472461b4845ea606a7fed_1", - "old_fingerprint": "29170146f7ca0a20898163aad42ffe78_1", - "code_extract": "var hashmd5 = crypto.createHash(\\"md5\\").update(user.password);" - }, - { - "cwe_ids": [ - "326" - ], - "id": "javascript_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\\n✅ Use a recommended hashing library such as Argon2id for passwords\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2id })\\n\`\`\`\\n\\n## Resources\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_hash_md5", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/md5_password.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 9, - "end": 9, - "column": { - "start": 25, - "end": 38 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 12, - "end": 39 - }, - "content": "CryptoJS.MD5(user.password)" - }, - "parent_line_number": 9, - "snippet": "CryptoJS.MD5(user.password)", - "fingerprint": "842bae8a65c472461b4845ea606a7fed_2", - "old_fingerprint": "29170146f7ca0a20898163aad42ffe78_2", - "code_extract": "var hash = CryptoJS.MD5(user.password);" - } - ] -}" -`; - -exports[`javascript_lang_weak_password_hash_md5 ok_not_a_password 1`] = `"{}"`; diff --git a/tests/javascript/lang/weak_password_hash_md5/test.js b/tests/javascript/lang/weak_password_hash_md5/test.js index e33e9f313..b332c1205 100644 --- a/tests/javascript/lang/weak_password_hash_md5/test.js +++ b/tests/javascript/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_password", () => { + const testCase = "md5_password.js" + + const results = invoke(testCase) - test("md5_password", () => { - const testCase = "md5_password.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_not_a_password", () => { - const testCase = "ok_not_a_password.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_not_a_password", () => { + const testCase = "ok_not_a_password.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/weak_password_hash_md5/testdata/md5_password.js b/tests/javascript/lang/weak_password_hash_md5/testdata/md5_password.js index 1a933e02a..f975aab8a 100644 --- a/tests/javascript/lang/weak_password_hash_md5/testdata/md5_password.js +++ b/tests/javascript/lang/weak_password_hash_md5/testdata/md5_password.js @@ -1,11 +1,14 @@ var crypto = require("crypto"); var key = "secret key"; +// bearer:expected javascript_lang_weak_password_hash_md5 var encrypted = crypto.createHmac("md5", key).update(user.password); +// bearer:expected javascript_lang_weak_password_hash_md5 var hashmd5 = crypto.createHash("md5").update(user.password); import { CryptoJS } from "crypto-js" +// bearer:expected javascript_lang_weak_password_hash_md5 var hash = CryptoJS.MD5(user.password); var md5 = require('md5'); diff --git a/tests/javascript/lang/weak_password_hash_sha1/__snapshots__/test.js.snap b/tests/javascript/lang/weak_password_hash_sha1/__snapshots__/test.js.snap deleted file mode 100644 index 3a5321824..000000000 --- a/tests/javascript/lang/weak_password_hash_sha1/__snapshots__/test.js.snap +++ /dev/null @@ -1,178 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_weak_password_hash_sha1 ok_not_a_password 1`] = `"{}"`; - -exports[`javascript_lang_weak_password_hash_sha1 sha1_password 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "326" - ], - "id": "javascript_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\\n✅ Use a recommended hashing library such as Argon2id for passwords\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2id })\\n\`\`\`\\n\\n## Resources\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_hash_sha1", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/sha1_password.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 4, - "end": 4, - "column": { - "start": 55, - "end": 68 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 17, - "end": 69 - }, - "content": "crypto.createHmac(\\"sha1\\", key).update(user.password)" - }, - "parent_line_number": 4, - "snippet": "crypto.createHmac(\\"sha1\\", key).update(user.password)", - "fingerprint": "3d1a07c8b1dd26c04fc9b527f0319cd1_0", - "old_fingerprint": "9c6e96dadebf3bae6b4479e7ce3511d9_0", - "code_extract": "var encrypted = crypto.createHmac(\\"sha1\\", key).update(user.password);" - }, - { - "cwe_ids": [ - "326" - ], - "id": "javascript_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\\n✅ Use a recommended hashing library such as Argon2id for passwords\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2id })\\n\`\`\`\\n\\n## Resources\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_hash_sha1", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/sha1_password.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 48, - "end": 61 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 15, - "end": 62 - }, - "content": "crypto.createHash(\\"sha1\\").update(user.password)" - }, - "parent_line_number": 5, - "snippet": "crypto.createHash(\\"sha1\\").update(user.password)", - "fingerprint": "3d1a07c8b1dd26c04fc9b527f0319cd1_1", - "old_fingerprint": "9c6e96dadebf3bae6b4479e7ce3511d9_1", - "code_extract": "var shaHash = crypto.createHash(\\"sha1\\").update(user.password);" - }, - { - "cwe_ids": [ - "326" - ], - "id": "javascript_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\\n✅ Use a recommended hashing library such as Argon2id for passwords\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2id })\\n\`\`\`\\n\\n## Resources\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_hash_sha1", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/sha1_password.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 7, - "end": 7, - "column": { - "start": 19, - "end": 32 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 1, - "end": 40 - }, - "content": "CryptoJS.HmacSHA1(user.password, \\"Key\\")" - }, - "parent_line_number": 7, - "snippet": "CryptoJS.HmacSHA1(user.password, \\"Key\\")", - "fingerprint": "3d1a07c8b1dd26c04fc9b527f0319cd1_2", - "old_fingerprint": "9c6e96dadebf3bae6b4479e7ce3511d9_2", - "code_extract": "CryptoJS.HmacSHA1(user.password, \\"Key\\")" - }, - { - "cwe_ids": [ - "326" - ], - "id": "javascript_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\\n✅ Use a recommended hashing library such as Argon2id for passwords\\n\\n\`\`\`javascript\\n const argon2 = require(\\"argon2\\");\\n\\n const hash = await argon2.hash(req.params.password, { type: argon2.argon2id })\\n\`\`\`\\n\\n## Resources\\n- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_weak_password_hash_sha1", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/sha1_password.js", - "filename": ".", - "data_type": { - "category_uuid": "dd88aee5-9d40-4ad2-8983-0c791ddec47c", - "name": "Passwords" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 8, - "end": 8, - "column": { - "start": 15, - "end": 28 - } - }, - "sink": { - "start": 8, - "end": 8, - "column": { - "start": 1, - "end": 29 - }, - "content": "CryptoJS.SHA1(user.password)" - }, - "parent_line_number": 8, - "snippet": "CryptoJS.SHA1(user.password)", - "fingerprint": "3d1a07c8b1dd26c04fc9b527f0319cd1_3", - "old_fingerprint": "9c6e96dadebf3bae6b4479e7ce3511d9_3", - "code_extract": "CryptoJS.SHA1(user.password)" - } - ] -}" -`; diff --git a/tests/javascript/lang/weak_password_hash_sha1/test.js b/tests/javascript/lang/weak_password_hash_sha1/test.js index 01ca08809..f72620b0a 100644 --- a/tests/javascript/lang/weak_password_hash_sha1/test.js +++ b/tests/javascript/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.js" + + const results = invoke(testCase) - test("ok_not_a_password", () => { - const testCase = "ok_not_a_password.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("sha1_password", () => { - const testCase = "sha1_password.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("sha1_password", () => { + const testCase = "sha1_password.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/weak_password_hash_sha1/testdata/sha1_password.js b/tests/javascript/lang/weak_password_hash_sha1/testdata/sha1_password.js index 1f939668c..b017f8d65 100644 --- a/tests/javascript/lang/weak_password_hash_sha1/testdata/sha1_password.js +++ b/tests/javascript/lang/weak_password_hash_sha1/testdata/sha1_password.js @@ -1,8 +1,12 @@ var crypto = require("crypto"); var key = "secret key"; +// bearer:expected javascript_lang_weak_password_hash_sha1 var encrypted = crypto.createHmac("sha1", key).update(user.password); +// bearer:expected javascript_lang_weak_password_hash_sha1 var shaHash = crypto.createHash("sha1").update(user.password); +// bearer:expected javascript_lang_weak_password_hash_sha1 CryptoJS.HmacSHA1(user.password, "Key") +// bearer:expected javascript_lang_weak_password_hash_sha1 CryptoJS.SHA1(user.password) diff --git a/tests/javascript/lang/websocket_insecure/__snapshots__/test.js.snap b/tests/javascript/lang/websocket_insecure/__snapshots__/test.js.snap deleted file mode 100644 index 05a052619..000000000 --- a/tests/javascript/lang/websocket_insecure/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_lang_websocket_insecure bad 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "319" - ], - "id": "javascript_lang_websocket_insecure", - "title": "Usage of insecure websocket connection", - "description": "## Description\\n\\nApplications should only connect to APIs using SSL connections. This rule\\nchecks that all websocket connections use SSL.\\n\\n## Remediations\\n\\n❌ Avoid using unsecured outgoing websocket communication:\\n\\n\`\`\`javascript\\nconst client = new WebSocket('ws://insecure-api.com')\\n\`\`\`\\n\\n✅ Always connect using SSL:\\n\\n\`\`\`javascript\\nconst client = new WebSocket('wss://secure-api.com')\\n\`\`\`\\n\\n## Resources\\n- [OWASP insecure transport](https://owasp.org/www-community/vulnerabilities/Insecure_Transport)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_lang_websocket_insecure", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/bad.js", - "filename": ".", - "source": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 39 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 39 - }, - "content": "new WebSocket(\\"ws://insecure.com\\", {})" - }, - "parent_line_number": 1, - "snippet": "new WebSocket(\\"ws://insecure.com\\", {})", - "fingerprint": "7d7297b3ec21011189ac2e8ca42c0c5c_0", - "old_fingerprint": "f569dc1ef06ca2fd4f415f75fe54a1ae_0", - "code_extract": "new WebSocket(\\"ws://insecure.com\\", {})" - } - ] -}" -`; - -exports[`javascript_lang_websocket_insecure ok 1`] = `"{}"`; diff --git a/tests/javascript/lang/websocket_insecure/test.js b/tests/javascript/lang/websocket_insecure/test.js index fa284d13a..fc42999a0 100644 --- a/tests/javascript/lang/websocket_insecure/test.js +++ b/tests/javascript/lang/websocket_insecure/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.js" + + const results = invoke(testCase) - test("bad", () => { - const testCase = "bad.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok", () => { - const testCase = "ok.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok", () => { + const testCase = "ok.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/lang/websocket_insecure/testdata/bad.js b/tests/javascript/lang/websocket_insecure/testdata/bad.js index 92fffc9ba..8789a479d 100644 --- a/tests/javascript/lang/websocket_insecure/testdata/bad.js +++ b/tests/javascript/lang/websocket_insecure/testdata/bad.js @@ -1 +1,2 @@ +// bearer:expected javascript_lang_websocket_insecure new WebSocket("ws://insecure.com", {}) diff --git a/tests/javascript/react/dangerously_set_inner_html/__snapshots__/test.js.snap b/tests/javascript/react/dangerously_set_inner_html/__snapshots__/test.js.snap deleted file mode 100644 index d8f9e75cb..000000000 --- a/tests/javascript/react/dangerously_set_inner_html/__snapshots__/test.js.snap +++ /dev/null @@ -1,91 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_react_dangerously_set_inner_html insecure-raw_input 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_react_dangerously_set_inner_html", - "title": "Unsanitized user input in React inner HTML method (XSS)", - "description": "## Description\\nThere are Cross-Site Scripting (XSS) vulnerabilites when using React's dangerouslySetInnerHTML with unsanitized data.\\n\\n## Remediations\\n✅ Sanitize data when using dangerouslySetInnerHTML\\n\\n\`\`\`javascript\\n \\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_react_dangerously_set_inner_html", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure-raw_input.js", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 52, - "end": 69 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 52, - "end": 69 - }, - "content": "{ __html: input }" - }, - "parent_line_number": 2, - "snippet": "{ __html: input }", - "fingerprint": "d22d7ec8e5e9695e2f1909d8059d96df_0", - "old_fingerprint": "800f90fcc888d200ca077ff5e100b72d_0", - "code_extract": "\\t
  • ;" - } - ] -}" -`; - -exports[`javascript_react_dangerously_set_inner_html insecure-template_string 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_react_dangerously_set_inner_html", - "title": "Unsanitized user input in React inner HTML method (XSS)", - "description": "## Description\\nThere are Cross-Site Scripting (XSS) vulnerabilites when using React's dangerouslySetInnerHTML with unsanitized data.\\n\\n## Remediations\\n✅ Sanitize data when using dangerouslySetInnerHTML\\n\\n\`\`\`javascript\\n \\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_react_dangerously_set_inner_html", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/insecure-template_string.js", - "filename": ".", - "source": { - "start": 4, - "end": 4, - "column": { - "start": 28, - "end": 72 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 28, - "end": 72 - }, - "content": "{ __html: \`home page\` }" - }, - "parent_line_number": 4, - "snippet": "{ __html: \`home page\` }", - "fingerprint": "d22d7ec8e5e9695e2f1909d8059d96df_0", - "old_fingerprint": "aa5f0c01827445feeda685b3e0490112_0", - "code_extract": "\\t\\tdangerouslySetInnerHTML={{ __html: \`home page\` }}" - } - ] -}" -`; - -exports[`javascript_react_dangerously_set_inner_html secure-dom-purify 1`] = `"{}"`; - -exports[`javascript_react_dangerously_set_inner_html secure-render-markdown 1`] = `"{}"`; - -exports[`javascript_react_dangerously_set_inner_html secure-sanitize 1`] = `"{}"`; - -exports[`javascript_react_dangerously_set_inner_html secure-template_string 1`] = `"{}"`; diff --git a/tests/javascript/react/dangerously_set_inner_html/test.js b/tests/javascript/react/dangerously_set_inner_html/test.js index 78aeed284..16e8c1c3e 100644 --- a/tests/javascript/react/dangerously_set_inner_html/test.js +++ b/tests/javascript/react/dangerously_set_inner_html/test.js @@ -1,36 +1,70 @@ -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) - - test("insecure-raw_input", () => { - const testCase = "insecure-raw_input.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("insecure-template_string", () => { - const testCase = "insecure-template_string.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("secure-render-markdown", () => { - const testCase = "secure-render-markdown.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("secure-sanitize", () => { - const testCase = "secure-sanitize.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("secure-template_string", () => { - const testCase = "secure-template_string.js" - expect(invoke(testCase)).toMatchSnapshot() - }) - - test("secure-dom-purify", () => { - const testCase = "secure-dom_purify.tsx" - expect(invoke(testCase)).toMatchSnapshot() - }) -}) + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + + test("insecure-raw_input", () => { + const testCase = "insecure-raw_input.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("insecure-template_string", () => { + const testCase = "insecure-template_string.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("secure-dom_purify", () => { + const testCase = "secure-dom_purify.tsx" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("secure-render-markdown", () => { + const testCase = "secure-render-markdown.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("secure-sanitize", () => { + const testCase = "secure-sanitize.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + + test("secure-template_string", () => { + const testCase = "secure-template_string.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + +}) \ No newline at end of file diff --git a/tests/javascript/react/dangerously_set_inner_html/testdata/insecure-raw_input.js b/tests/javascript/react/dangerously_set_inner_html/testdata/insecure-raw_input.js index 6f74d0e2a..c2fb7db0b 100644 --- a/tests/javascript/react/dangerously_set_inner_html/testdata/insecure-raw_input.js +++ b/tests/javascript/react/dangerously_set_inner_html/testdata/insecure-raw_input.js @@ -1,3 +1,4 @@ function GetListItem(input) { +// bearer:expected javascript_react_dangerously_set_inner_html
  • ; } diff --git a/tests/javascript/react/dangerously_set_inner_html/testdata/insecure-template_string.js b/tests/javascript/react/dangerously_set_inner_html/testdata/insecure-template_string.js index 9f4c409c9..ad675a1b8 100644 --- a/tests/javascript/react/dangerously_set_inner_html/testdata/insecure-template_string.js +++ b/tests/javascript/react/dangerously_set_inner_html/testdata/insecure-template_string.js @@ -1,6 +1,7 @@ function GetListItem(input) {
  • home page` }} />; } diff --git a/tests/javascript/react/google_analytics/__snapshots__/test.js.snap b/tests/javascript/react/google_analytics/__snapshots__/test.js.snap deleted file mode 100644 index 3d9012954..000000000 --- a/tests/javascript/react/google_analytics/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_react_google_analytics insecure 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_react_google_analytics", - "title": "Leakage of sensitive data to Google Analytics (React)", - "description": "## Description\\n\\nLeaking sensitive data to third-party analytics tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Google Analytics.\\n\\n## Remediations\\n\\nWhen sending data to analytics libraries, ensure all sensitive data is removed.\\n\\n\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_react_google_analytics", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 9, - "end": 19 - } - }, - "sink": { - "start": 2, - "end": 6, - "column": { - "start": 1, - "end": 3 - }, - "content": "ReactGA.event({\\n\\tcategory: \\"user\\",\\n\\taction: \\"logged_in\\",\\n\\tvalue: user.email,\\n})" - }, - "parent_line_number": 2, - "snippet": "ReactGA.event({\\n\\tcategory: \\"user\\",\\n\\taction: \\"logged_in\\",\\n\\tvalue: user.email,\\n})", - "fingerprint": "16009a30042a079495df4d1ac0b9b830_0", - "old_fingerprint": "03f5db1bd9f0262529b5d9614e2d889f_0", - "code_extract": "ReactGA.event({\\n\\tcategory: \\"user\\",\\n\\taction: \\"logged_in\\",\\n\\tvalue: user.email,\\n});" - } - ] -}" -`; - -exports[`javascript_react_google_analytics secure 1`] = `"{}"`; diff --git a/tests/javascript/react/google_analytics/test.js b/tests/javascript/react/google_analytics/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/react/google_analytics/test.js +++ b/tests/javascript/react/google_analytics/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/react/google_analytics/testdata/insecure.js b/tests/javascript/react/google_analytics/testdata/insecure.js index f62ae7d66..0e03d71aa 100644 --- a/tests/javascript/react/google_analytics/testdata/insecure.js +++ b/tests/javascript/react/google_analytics/testdata/insecure.js @@ -1,4 +1,5 @@ const user = { email: "jhon@gmail.com " }; +// bearer:expected javascript_react_google_analytics ReactGA.event({ category: "user", action: "logged_in", diff --git a/tests/javascript/third_parties/airbrake/__snapshots__/test.js.snap b/tests/javascript/third_parties/airbrake/__snapshots__/test.js.snap deleted file mode 100644 index 1369ead6f..000000000 --- a/tests/javascript/third_parties/airbrake/__snapshots__/test.js.snap +++ /dev/null @@ -1,93 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_airbrake datatype_in_notify 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_airbrake", - "title": "Leakage of sensitive data to Airbrake", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Airbrake.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\nairbrake.notify({\\n error: err,\\n params: { user: user.uuid },\\n});\\n\`\`\`\\n\\n## Resources\\n- [Airbrake Docs](https://docs.airbrake.io/)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_airbrake", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/datatype_in_notify.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 9, - "end": 9, - "column": { - "start": 41, - "end": 67 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 15, - "end": 68 - }, - "content": "airbrake.notify(\\"user \\" + currentUser().emailAddress)" - }, - "parent_line_number": 9, - "snippet": "airbrake.notify(\\"user \\" + currentUser().emailAddress)", - "fingerprint": "b062988f903356f85f1052011a6c72d0_0", - "old_fingerprint": "f9bd32bc01740503cc34d336db979930_0", - "code_extract": "let promise = airbrake.notify(\\"user \\" + currentUser().emailAddress)" - }, - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_airbrake", - "title": "Leakage of sensitive data to Airbrake", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Airbrake.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\nairbrake.notify({\\n error: err,\\n params: { user: user.uuid },\\n});\\n\`\`\`\\n\\n## Resources\\n- [Airbrake Docs](https://docs.airbrake.io/)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_airbrake", - "line_number": 16, - "full_filename": "/tmp/bearer-scan/datatype_in_notify.js", - "filename": ".", - "data_type": { - "category_uuid": "b5a3b0fd-dd5c-420d-91ce-dd2dddc8cc38", - "name": "IP address" - }, - "category_groups": [ - "Personal Data" - ], - "source": { - "start": 18, - "end": 18, - "column": { - "start": 23, - "end": 37 - } - }, - "sink": { - "start": 16, - "end": 19, - "column": { - "start": 5, - "end": 7 - }, - "content": "airbrake.notify({\\n error: err,\\n params: { user: user.ipAddress },\\n })" - }, - "parent_line_number": 16, - "snippet": "airbrake.notify({\\n error: err,\\n params: { user: user.ipAddress },\\n })", - "fingerprint": "b062988f903356f85f1052011a6c72d0_1", - "old_fingerprint": "f9bd32bc01740503cc34d336db979930_1", - "code_extract": " airbrake.notify({\\n error: err,\\n params: { user: user.ipAddress },\\n });" - } - ] -}" -`; - -exports[`javascript_third_parties_airbrake ok_no_datatype 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/airbrake/test.js b/tests/javascript/third_parties/airbrake/test.js index 3039b73b6..1b8019623 100644 --- a/tests/javascript/third_parties/airbrake/test.js +++ b/tests/javascript/third_parties/airbrake/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("datatype_in_notify", () => { + const testCase = "datatype_in_notify.js" + + const results = invoke(testCase) - test("datatype_in_notify", () => { - const testCase = "datatype_in_notify.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_no_datatype", () => { - const testCase = "ok_no_datatype.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_no_datatype", () => { + const testCase = "ok_no_datatype.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/airbrake/testdata/datatype_in_notify.js b/tests/javascript/third_parties/airbrake/testdata/datatype_in_notify.js index 114480e69..27559579b 100644 --- a/tests/javascript/third_parties/airbrake/testdata/datatype_in_notify.js +++ b/tests/javascript/third_parties/airbrake/testdata/datatype_in_notify.js @@ -6,6 +6,7 @@ const airbrake = new Notifier({ environment: 'PROD', }); +// bearer:expected javascript_third_parties_airbrake let promise = airbrake.notify("user " + currentUser().emailAddress) promise.then(() => {}) @@ -13,6 +14,7 @@ riskyCode(() => { try { // something risky } catch (err) { +// bearer:expected javascript_third_parties_airbrake airbrake.notify({ error: err, params: { user: user.ipAddress }, diff --git a/tests/javascript/third_parties/algolia/__snapshots__/test.js.snap b/tests/javascript/third_parties/algolia/__snapshots__/test.js.snap deleted file mode 100644 index f37bfa0b9..000000000 --- a/tests/javascript/third_parties/algolia/__snapshots__/test.js.snap +++ /dev/null @@ -1,140 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_algolia datatype_in_index 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_algolia", - "title": "Leakage of sensitive data to Algolia", - "description": "## Description\\nLeaking sensitive data to third-party data tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Algolia.\\n\\n## Remediations\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n const algoliaSearch = require('algoliasearch')\\n const myAlgolia = algoliaSearch(\\"123\\", \\"123\\")\\n const index = myAlgolia.initIndex(user.uuid)\\n\`\`\`\\n\\n## Resources\\n- [Algolia docs](https://www.algolia.com/doc/)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_algolia", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/datatype_in_index.js", - "filename": ".", - "data_type": { - "category_uuid": "7a794bd6-a6d1-429d-91a2-377acce9e9db", - "name": "Bank Account" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 4, - "end": 4, - "column": { - "start": 35, - "end": 62 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 15, - "end": 63 - }, - "content": "myAlgolia.initIndex(company.bank_account_number)" - }, - "parent_line_number": 4, - "snippet": "myAlgolia.initIndex(company.bank_account_number)", - "fingerprint": "3b8a9db66a5d96671524cd36226b34d5_0", - "old_fingerprint": "06d0cf262781955d2293578d29424a6f_0", - "code_extract": "const index = myAlgolia.initIndex(company.bank_account_number)" - } - ] -}" -`; - -exports[`javascript_third_parties_algolia datatype_in_save_object 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_algolia", - "title": "Leakage of sensitive data to Algolia", - "description": "## Description\\nLeaking sensitive data to third-party data tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Algolia.\\n\\n## Remediations\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n const algoliaSearch = require('algoliasearch')\\n const myAlgolia = algoliaSearch(\\"123\\", \\"123\\")\\n const index = myAlgolia.initIndex(user.uuid)\\n\`\`\`\\n\\n## Resources\\n- [Algolia docs](https://www.algolia.com/doc/)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_algolia", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/datatype_in_save_object.js", - "filename": ".", - "data_type": { - "category_uuid": "b5a3b0fd-dd5c-420d-91ce-dd2dddc8cc38", - "name": "IP address" - }, - "category_groups": [ - "Personal Data" - ], - "source": { - "start": 7, - "end": 7, - "column": { - "start": 19, - "end": 43 - } - }, - "sink": { - "start": 8, - "end": 9, - "column": { - "start": 1, - "end": 65 - }, - "content": "index\\n .saveObject(userObj, { autoGenerateObjectIDIfNotExist: true })" - }, - "parent_line_number": 8, - "snippet": "index\\n .saveObject(userObj, { autoGenerateObjectIDIfNotExist: true })", - "fingerprint": "3b8a9db66a5d96671524cd36226b34d5_0", - "old_fingerprint": "38d2aaad78cefccc70a267a9100219ff_0", - "code_extract": "index\\n .saveObject(userObj, { autoGenerateObjectIDIfNotExist: true })" - }, - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_algolia", - "title": "Leakage of sensitive data to Algolia", - "description": "## Description\\nLeaking sensitive data to third-party data tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Algolia.\\n\\n## Remediations\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n const algoliaSearch = require('algoliasearch')\\n const myAlgolia = algoliaSearch(\\"123\\", \\"123\\")\\n const index = myAlgolia.initIndex(user.uuid)\\n\`\`\`\\n\\n## Resources\\n- [Algolia docs](https://www.algolia.com/doc/)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_algolia", - "line_number": 12, - "full_filename": "/tmp/bearer-scan/datatype_in_save_object.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 12, - "end": 12, - "column": { - "start": 29, - "end": 39 - } - }, - "sink": { - "start": 12, - "end": 12, - "column": { - "start": 1, - "end": 43 - }, - "content": "index.saveObjects([{ email: user.email }])" - }, - "parent_line_number": 12, - "snippet": "index.saveObjects([{ email: user.email }])", - "fingerprint": "3b8a9db66a5d96671524cd36226b34d5_1", - "old_fingerprint": "38d2aaad78cefccc70a267a9100219ff_1", - "code_extract": "index.saveObjects([{ email: user.email }])" - } - ] -}" -`; diff --git a/tests/javascript/third_parties/algolia/test.js b/tests/javascript/third_parties/algolia/test.js index 25d6d106e..79c8346bf 100644 --- a/tests/javascript/third_parties/algolia/test.js +++ b/tests/javascript/third_parties/algolia/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("datatype_in_index", () => { + const testCase = "datatype_in_index.js" + + const results = invoke(testCase) - test("datatype_in_index", () => { - const testCase = "datatype_in_index.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_save_object", () => { - const testCase = "datatype_in_save_object.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_save_object", () => { + const testCase = "datatype_in_save_object.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/algolia/testdata/datatype_in_index.js b/tests/javascript/third_parties/algolia/testdata/datatype_in_index.js index c04866d3a..fbed93c69 100644 --- a/tests/javascript/third_parties/algolia/testdata/datatype_in_index.js +++ b/tests/javascript/third_parties/algolia/testdata/datatype_in_index.js @@ -1,5 +1,6 @@ const algoliasearch = require('algoliasearch') const myAlgolia = algoliasearch("123", "123") +// bearer:expected javascript_third_parties_algolia const index = myAlgolia.initIndex(company.bank_account_number) diff --git a/tests/javascript/third_parties/algolia/testdata/datatype_in_save_object.js b/tests/javascript/third_parties/algolia/testdata/datatype_in_save_object.js index 88d03a225..231966192 100644 --- a/tests/javascript/third_parties/algolia/testdata/datatype_in_save_object.js +++ b/tests/javascript/third_parties/algolia/testdata/datatype_in_save_object.js @@ -5,10 +5,12 @@ const index = myAlgolia.initIndex("test_index") // saveObject const userObj = { user_id: user.ip_address } +// bearer:expected javascript_third_parties_algolia index .saveObject(userObj, { autoGenerateObjectIDIfNotExist: true }) .then(console.log("obj saved")) +// bearer:expected javascript_third_parties_algolia index.saveObjects([{ email: user.email }]) diff --git a/tests/javascript/third_parties/bugsnag/__snapshots__/test.js.snap b/tests/javascript/third_parties/bugsnag/__snapshots__/test.js.snap deleted file mode 100644 index 3b3558def..000000000 --- a/tests/javascript/third_parties/bugsnag/__snapshots__/test.js.snap +++ /dev/null @@ -1,198 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_bugsnag datatype_in_breadcrumb 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_bugsnag", - "title": "Leakage of sensitive data to Bugsnag", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Bugsnag.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n import { Bugsnag } from \\"@bugsnag/js\\"\\n\\n var bugSession = Bugsnag.startSession()\\n bugSession.notify(user.uuid)\\n\`\`\`\\n\\n## Resources\\n- [Bugsnag Docs](https://docs.bugsnag.com/platforms/javascript/)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_bugsnag", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/datatype_in_breadcrumb.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 1, - "end": 1, - "column": { - "start": 25, - "end": 35 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 36 - }, - "content": "Bugsnag.leaveBreadcrumb(user.email)" - }, - "parent_line_number": 1, - "snippet": "Bugsnag.leaveBreadcrumb(user.email)", - "fingerprint": "4ed64b524e1062cd19e85082c56d7357_0", - "old_fingerprint": "9717161f6e1f94bbd3de51f7be3b004f_0", - "code_extract": "Bugsnag.leaveBreadcrumb(user.email)" - } - ] -}" -`; - -exports[`javascript_third_parties_bugsnag datatype_in_notify 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_bugsnag", - "title": "Leakage of sensitive data to Bugsnag", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Bugsnag.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n import { Bugsnag } from \\"@bugsnag/js\\"\\n\\n var bugSession = Bugsnag.startSession()\\n bugSession.notify(user.uuid)\\n\`\`\`\\n\\n## Resources\\n- [Bugsnag Docs](https://docs.bugsnag.com/platforms/javascript/)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_bugsnag", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/datatype_in_notify.js", - "filename": ".", - "data_type": { - "category_uuid": "b5a3b0fd-dd5c-420d-91ce-dd2dddc8cc38", - "name": "IP address" - }, - "category_groups": [ - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 20, - "end": 35 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 5, - "end": 48 - }, - "content": "Bugsnag.notify(user.ip_address + \\" : \\" + e)" - }, - "parent_line_number": 5, - "snippet": "Bugsnag.notify(user.ip_address + \\" : \\" + e)", - "fingerprint": "4ed64b524e1062cd19e85082c56d7357_0", - "old_fingerprint": "2600f103b2022b74b701bf181d930726_0", - "code_extract": " Bugsnag.notify(user.ip_address + \\" : \\" + e)" - } - ] -}" -`; - -exports[`javascript_third_parties_bugsnag datatype_in_session 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_bugsnag", - "title": "Leakage of sensitive data to Bugsnag", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Bugsnag.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n import { Bugsnag } from \\"@bugsnag/js\\"\\n\\n var bugSession = Bugsnag.startSession()\\n bugSession.notify(user.uuid)\\n\`\`\`\\n\\n## Resources\\n- [Bugsnag Docs](https://docs.bugsnag.com/platforms/javascript/)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_bugsnag", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/datatype_in_session.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 4, - "end": 4, - "column": { - "start": 19, - "end": 29 - } - }, - "sink": { - "start": 4, - "end": 4, - "column": { - "start": 1, - "end": 30 - }, - "content": "bugSession.notify(user.email)" - }, - "parent_line_number": 4, - "snippet": "bugSession.notify(user.email)", - "fingerprint": "4ed64b524e1062cd19e85082c56d7357_0", - "old_fingerprint": "f9b5504b668494291b95b2caaaea43a7_0", - "code_extract": "bugSession.notify(user.email)" - } - ] -}" -`; - -exports[`javascript_third_parties_bugsnag datatype_in_start 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_bugsnag", - "title": "Leakage of sensitive data to Bugsnag", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Bugsnag.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n import { Bugsnag } from \\"@bugsnag/js\\"\\n\\n var bugSession = Bugsnag.startSession()\\n bugSession.notify(user.uuid)\\n\`\`\`\\n\\n## Resources\\n- [Bugsnag Docs](https://docs.bugsnag.com/platforms/javascript/)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_bugsnag", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/datatype_in_start.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 24, - "end": 34 - } - }, - "sink": { - "start": 1, - "end": 11, - "column": { - "start": 1, - "end": 3 - }, - "content": "Bugsnag.start({\\n onError: function (e) {\\n e.setUser(user.id, user.email, user.name)\\n e.addMetadata('user location', {\\n country: user.home_country,\\n })\\n },\\n onSession: function (session) {\\n session.setUser(user.email)\\n }\\n})" - }, - "parent_line_number": 1, - "snippet": "Bugsnag.start({\\n onError: function (e) {\\n e.setUser(user.id, user.email, user.name)\\n e.addMetadata('user location', {\\n country: user.home_country,\\n })\\n },\\n onSession: function (session) {\\n session.setUser(user.email)\\n }\\n})", - "fingerprint": "4ed64b524e1062cd19e85082c56d7357_0", - "old_fingerprint": "16c296d0999c2d095505c981bdb4e7df_0", - "code_extract": "Bugsnag.start({\\n onError: function (e) {\\n e.setUser(user.id, user.email, user.name)\\n e.addMetadata('user location', {\\n country: user.home_country,\\n })\\n },\\n onSession: function (session) {\\n session.setUser(user.email)\\n }\\n})" - } - ] -}" -`; - -exports[`javascript_third_parties_bugsnag ok_ignored_datatype_only 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/bugsnag/test.js b/tests/javascript/third_parties/bugsnag/test.js index bcdf1e8d5..9f003debd 100644 --- a/tests/javascript/third_parties/bugsnag/test.js +++ b/tests/javascript/third_parties/bugsnag/test.js @@ -1,37 +1,60 @@ -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("datatype_in_breadcrumb", () => { + const testCase = "datatype_in_breadcrumb.js" + + const results = invoke(testCase) - test("datatype_in_breadcrumb", () => { - const testCase = "datatype_in_breadcrumb.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_notify", () => { - const testCase = "datatype_in_notify.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_notify", () => { + const testCase = "datatype_in_notify.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_session", () => { - const testCase = "datatype_in_session.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_session", () => { + const testCase = "datatype_in_session.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_start", () => { - const testCase = "datatype_in_start.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_start", () => { + const testCase = "datatype_in_start.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_ignored_datatype_only", () => { - const testCase = "ok_ignored_datatype_only.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_ignored_datatype_only", () => { + const testCase = "ok_ignored_datatype_only.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/bugsnag/testdata/datatype_in_breadcrumb.js b/tests/javascript/third_parties/bugsnag/testdata/datatype_in_breadcrumb.js index 5abff609e..c043d1734 100644 --- a/tests/javascript/third_parties/bugsnag/testdata/datatype_in_breadcrumb.js +++ b/tests/javascript/third_parties/bugsnag/testdata/datatype_in_breadcrumb.js @@ -1 +1,2 @@ +// bearer:expected javascript_third_parties_bugsnag Bugsnag.leaveBreadcrumb(user.email) \ No newline at end of file diff --git a/tests/javascript/third_parties/bugsnag/testdata/datatype_in_notify.js b/tests/javascript/third_parties/bugsnag/testdata/datatype_in_notify.js index f0fa7bc85..67174bade 100644 --- a/tests/javascript/third_parties/bugsnag/testdata/datatype_in_notify.js +++ b/tests/javascript/third_parties/bugsnag/testdata/datatype_in_notify.js @@ -2,6 +2,7 @@ riskyCode(() => { try { // risky business } catch (e) { +// bearer:expected javascript_third_parties_bugsnag Bugsnag.notify(user.ip_address + " : " + e) } }) diff --git a/tests/javascript/third_parties/bugsnag/testdata/datatype_in_session.js b/tests/javascript/third_parties/bugsnag/testdata/datatype_in_session.js index 78a211c49..7b94fdce5 100644 --- a/tests/javascript/third_parties/bugsnag/testdata/datatype_in_session.js +++ b/tests/javascript/third_parties/bugsnag/testdata/datatype_in_session.js @@ -1,4 +1,5 @@ import { Bugsnag } from "@bugsnag/js" var bugSession = Bugsnag.startSession() +// bearer:expected javascript_third_parties_bugsnag bugSession.notify(user.email) \ No newline at end of file diff --git a/tests/javascript/third_parties/bugsnag/testdata/datatype_in_start.js b/tests/javascript/third_parties/bugsnag/testdata/datatype_in_start.js index f48bd359a..4bb82e3f9 100644 --- a/tests/javascript/third_parties/bugsnag/testdata/datatype_in_start.js +++ b/tests/javascript/third_parties/bugsnag/testdata/datatype_in_start.js @@ -1,3 +1,4 @@ +// bearer:expected javascript_third_parties_bugsnag Bugsnag.start({ onError: function (e) { e.setUser(user.id, user.email, user.name) diff --git a/tests/javascript/third_parties/datadog/__snapshots__/test.js.snap b/tests/javascript/third_parties/datadog/__snapshots__/test.js.snap deleted file mode 100644 index 9b1f36427..000000000 --- a/tests/javascript/third_parties/datadog/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_datadog insecure 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_datadog", - "title": "Leakage of sensitive data to Datadog", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Datadog.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n const StatsD = require(\\"hot-shots\\");\\n const client = new StatsD({\\n port: 8020,\\n globalTags: { env: process.env.NODE_ENV },\\n errorHandler: errorHandler,\\n });\\n\\n client.event(user.uuid, \\"logged_in\\", {});\\n\`\`\`\\n\\n## Resources\\n- [Datadog docs](https://docs.datadoghq.com)\\n- [Scrubbing data](https://docs.datadoghq.com/tracing/configure_data_security/?tab=mongodb#scrub-sensitive-data-from-your-spans)\\n- [OWASP logging cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_datadog", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 16, - "end": 28 - } - }, - "sink": { - "start": 11, - "end": 11, - "column": { - "start": 1, - "end": 44 - }, - "content": "client.event(\\"user\\", \\"logged_in\\", {}, user)" - }, - "parent_line_number": 11, - "snippet": "client.event(\\"user\\", \\"logged_in\\", {}, user)", - "fingerprint": "30198f8417f3252a9fc8b70f9affed31_0", - "old_fingerprint": "bb0eca4a79e471268a98871052b5e117_0", - "code_extract": "client.event(\\"user\\", \\"logged_in\\", {}, user);" - } - ] -}" -`; - -exports[`javascript_third_parties_datadog secure 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/datadog/test.js b/tests/javascript/third_parties/datadog/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/third_parties/datadog/test.js +++ b/tests/javascript/third_parties/datadog/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/datadog/testdata/insecure.js b/tests/javascript/third_parties/datadog/testdata/insecure.js index 5441f46de..80d2ccc55 100644 --- a/tests/javascript/third_parties/datadog/testdata/insecure.js +++ b/tests/javascript/third_parties/datadog/testdata/insecure.js @@ -8,4 +8,5 @@ const client = new StatsD({ errorHandler: errorHandler, }); +// bearer:expected javascript_third_parties_datadog client.event("user", "logged_in", {}, user); diff --git a/tests/javascript/third_parties/datadog_browser/__snapshots__/test.js.snap b/tests/javascript/third_parties/datadog_browser/__snapshots__/test.js.snap deleted file mode 100644 index 4ec9d49e8..000000000 --- a/tests/javascript/third_parties/datadog_browser/__snapshots__/test.js.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_datadog_browser insecure 1`] = ` -"{ - "low": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_datadog_browser", - "title": "Leakage of sensitive data to Datadog RUM", - "description": "## Description\\nSensitive and private data contained in your pages may be sent to datatdog to identify elements that a user interacted with.\\n\\n## Remediations\\n\\nTo control which information is sent to Datadog, manually set an action name, or implement a global scrubbing rule in the Datadog Browser SDK for RUM.\\n\\n## Resources\\n- [Datadog docs](https://docs.datadoghq.com)\\n- [Scrubbing data](https://docs.datadoghq.com/real_user_monitoring/browser/modifying_data_and_context/?tab=npm)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_datadog_browser", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 2, - "end": 29 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 2, - "end": 29 - }, - "content": "trackUserInteractions: true" - }, - "parent_line_number": 2, - "snippet": "trackUserInteractions: true", - "fingerprint": "b626a271a3e7a2abcbd7299cc0ca4fca_0", - "old_fingerprint": "e7395ebb254f0bc37f41ce5fad99985a_0", - "code_extract": "\\ttrackUserInteractions: true," - } - ] -}" -`; - -exports[`javascript_third_parties_datadog_browser secure 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/datadog_browser/test.js b/tests/javascript/third_parties/datadog_browser/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/third_parties/datadog_browser/test.js +++ b/tests/javascript/third_parties/datadog_browser/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/datadog_browser/testdata/insecure.js b/tests/javascript/third_parties/datadog_browser/testdata/insecure.js index 7636c27cf..1d83ac52f 100644 --- a/tests/javascript/third_parties/datadog_browser/testdata/insecure.js +++ b/tests/javascript/third_parties/datadog_browser/testdata/insecure.js @@ -1,3 +1,4 @@ DD_RUM.init({ +// bearer:expected javascript_third_parties_datadog_browser trackUserInteractions: true, }); diff --git a/tests/javascript/third_parties/dom_purify/__snapshots__/test.js.snap b/tests/javascript/third_parties/dom_purify/__snapshots__/test.js.snap deleted file mode 100644 index df5322536..000000000 --- a/tests/javascript/third_parties/dom_purify/__snapshots__/test.js.snap +++ /dev/null @@ -1,80 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_dom_purify insecure 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "79" - ], - "id": "javascript_third_parties_dom_purify", - "title": "Usage of vulnerable DOMPurify package (XSS)", - "description": "## Description\\nThere are XSS vulnerabilites when using DOMPurify's sanitize without proper configuration\\n\\n## Remediations\\n\\nSpecify a secure configuration option:\\n\`\`\`\\n DOMPurify.sanitize(htmlToSanitize, { RETURN_DOM_IMPORT:true })\\n\`\`\`\\n\\nor:\\n\\n\`\`\`\\n DOMPurify.sanitize(htmlToSanitize, { RETURN_DOM_FRAGMENT: true })\\n\`\`\`\\n\\n## Resources\\n- [Vulnerability explained](https://research.securitum.com/mutation-xss-via-mathml-mutation-dompurify-2-0-17-bypass)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_dom_purify", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure/insecure.js", - "filename": "insecure.js", - "source": { - "start": 2, - "end": 2, - "column": { - "start": 14, - "end": 47 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 14, - "end": 47 - }, - "content": "DOMPurify.sanitize(dirty, config)" - }, - "parent_line_number": 2, - "snippet": "DOMPurify.sanitize(dirty, config)", - "fingerprint": "e58733026a71734e4be7c15cc5b475ac_0", - "old_fingerprint": "38f5dacd3609670d15a3c1d7c8cb1968_0", - "code_extract": "const html = DOMPurify.sanitize(dirty, config);" - }, - { - "cwe_ids": [ - "79" - ], - "id": "javascript_third_parties_dom_purify", - "title": "Usage of vulnerable DOMPurify package (XSS)", - "description": "## Description\\nThere are XSS vulnerabilites when using DOMPurify's sanitize without proper configuration\\n\\n## Remediations\\n\\nSpecify a secure configuration option:\\n\`\`\`\\n DOMPurify.sanitize(htmlToSanitize, { RETURN_DOM_IMPORT:true })\\n\`\`\`\\n\\nor:\\n\\n\`\`\`\\n DOMPurify.sanitize(htmlToSanitize, { RETURN_DOM_FRAGMENT: true })\\n\`\`\`\\n\\n## Resources\\n- [Vulnerability explained](https://research.securitum.com/mutation-xss-via-mathml-mutation-dompurify-2-0-17-bypass)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_dom_purify", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/insecure/insecure.js", - "filename": "insecure.js", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 14, - "end": 39 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 14, - "end": 39 - }, - "content": "DOMPurify.sanitize(dirty)" - }, - "parent_line_number": 5, - "snippet": "DOMPurify.sanitize(dirty)", - "fingerprint": "e58733026a71734e4be7c15cc5b475ac_1", - "old_fingerprint": "38f5dacd3609670d15a3c1d7c8cb1968_1", - "code_extract": "const body = DOMPurify.sanitize(dirty);" - } - ] -}" -`; - -exports[`javascript_third_parties_dom_purify secure 1`] = `"{}"`; - -exports[`javascript_third_parties_dom_purify secure_dependency 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/dom_purify/test.js b/tests/javascript/third_parties/dom_purify/test.js index 55d3049bd..ea53e2b30 100644 --- a/tests/javascript/third_parties/dom_purify/test.js +++ b/tests/javascript/third_parties/dom_purify/test.js @@ -1,25 +1,36 @@ -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) - - - test("insecure", () => { - const testCase = "insecure" - expect(invoke(testCase)).toMatchSnapshot(); - }) - - - test("secure", () => { - const testCase = "secure" - expect(invoke(testCase)).toMatchSnapshot(); - }) - - - test("secure_dependency", () => { - const testCase = "secure_dependency" - expect(invoke(testCase)).toMatchSnapshot(); - }) - + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("insecure", () => { + const testCase = "insecure" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + test("secure", () => { + const testCase = "secure" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) + + test("secure_dependency", () => { + const testCase = "secure_dependency" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/dom_purify/testdata/insecure/insecure.js b/tests/javascript/third_parties/dom_purify/testdata/insecure/insecure.js index b999a19bd..f024a3f5b 100644 --- a/tests/javascript/third_parties/dom_purify/testdata/insecure/insecure.js +++ b/tests/javascript/third_parties/dom_purify/testdata/insecure/insecure.js @@ -1,5 +1,7 @@ const config = {}; +// bearer:expected javascript_third_parties_dom_purify const html = DOMPurify.sanitize(dirty, config); document.body.innerHTML = html; +// bearer:expected javascript_third_parties_dom_purify const body = DOMPurify.sanitize(dirty); \ No newline at end of file diff --git a/tests/javascript/third_parties/dynamodb_query_injection/__snapshots__/test.js.snap b/tests/javascript/third_parties/dynamodb_query_injection/__snapshots__/test.js.snap deleted file mode 100644 index 298e0f216..000000000 --- a/tests/javascript/third_parties/dynamodb_query_injection/__snapshots__/test.js.snap +++ /dev/null @@ -1,112 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_dynamodb_query_injection dynamodb_query_injection 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "943" - ], - "id": "javascript_third_parties_dynamodb_query_injection", - "title": "Unsanitized user input in DynamoDB query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw queries makes your application vulnerable to injection attacks.\\n\\n## Remediations\\n\\nNarrow down your query from the code instead of using unsanitzed user input to define it.\\n\\nExample:\\n\\n\`\`\`javascript\\nexports.handler = async function(event, context) {\\n var params = {\\n Key: {\\n \\"artist\\": {\\"S\\": event.input },\\n \\"song\\": {\\"S\\": \\"Carrot Eton\\"}\\n },\\n TableName: \\"artists\\"\\n };\\n var result = await dynamodb.getItem(params).promise()\\n console.log(JSON.stringify(result))\\n}\\n\`\`\`\\n\\n\\n## Resources\\n- [OWASP nosql injection explained](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_dynamodb_query_injection", - "line_number": 10, - "full_filename": "/tmp/bearer-scan/dynamodb_query_injection.js", - "filename": ".", - "source": { - "start": 10, - "end": 10, - "column": { - "start": 37, - "end": 61 - } - }, - "sink": { - "start": 10, - "end": 10, - "column": { - "start": 37, - "end": 61 - }, - "content": "new QueryCommand(params)" - }, - "parent_line_number": 10, - "snippet": "new QueryCommand(params)", - "fingerprint": "d3d9829e398dc3fa0b84684d1f8da7ef_0", - "old_fingerprint": "f80826420da7749a22d012e08e53f48f_0", - "code_extract": " const data = await ddbClient.send(new QueryCommand(params));" - }, - { - "cwe_ids": [ - "943" - ], - "id": "javascript_third_parties_dynamodb_query_injection", - "title": "Unsanitized user input in DynamoDB query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw queries makes your application vulnerable to injection attacks.\\n\\n## Remediations\\n\\nNarrow down your query from the code instead of using unsanitzed user input to define it.\\n\\nExample:\\n\\n\`\`\`javascript\\nexports.handler = async function(event, context) {\\n var params = {\\n Key: {\\n \\"artist\\": {\\"S\\": event.input },\\n \\"song\\": {\\"S\\": \\"Carrot Eton\\"}\\n },\\n TableName: \\"artists\\"\\n };\\n var result = await dynamodb.getItem(params).promise()\\n console.log(JSON.stringify(result))\\n}\\n\`\`\`\\n\\n\\n## Resources\\n- [OWASP nosql injection explained](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_dynamodb_query_injection", - "line_number": 18, - "full_filename": "/tmp/bearer-scan/dynamodb_query_injection.js", - "filename": ".", - "source": { - "start": 18, - "end": 18, - "column": { - "start": 3, - "end": 68 - } - }, - "sink": { - "start": 18, - "end": 18, - "column": { - "start": 3, - "end": 68 - }, - "content": "docClient.query(event[\\"query\\"][\\"params\\"], function(err, data) {})" - }, - "parent_line_number": 18, - "snippet": "docClient.query(event[\\"query\\"][\\"params\\"], function(err, data) {})", - "fingerprint": "d3d9829e398dc3fa0b84684d1f8da7ef_1", - "old_fingerprint": "f80826420da7749a22d012e08e53f48f_1", - "code_extract": " docClient.query(event[\\"query\\"][\\"params\\"], function(err, data) {});" - }, - { - "cwe_ids": [ - "943" - ], - "id": "javascript_third_parties_dynamodb_query_injection", - "title": "Unsanitized user input in DynamoDB query", - "description": "## Description\\nIncluding unsanitized data, such as user input or request data, in raw queries makes your application vulnerable to injection attacks.\\n\\n## Remediations\\n\\nNarrow down your query from the code instead of using unsanitzed user input to define it.\\n\\nExample:\\n\\n\`\`\`javascript\\nexports.handler = async function(event, context) {\\n var params = {\\n Key: {\\n \\"artist\\": {\\"S\\": event.input },\\n \\"song\\": {\\"S\\": \\"Carrot Eton\\"}\\n },\\n TableName: \\"artists\\"\\n };\\n var result = await dynamodb.getItem(params).promise()\\n console.log(JSON.stringify(result))\\n}\\n\`\`\`\\n\\n\\n## Resources\\n- [OWASP nosql injection explained](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_dynamodb_query_injection", - "line_number": 32, - "full_filename": "/tmp/bearer-scan/dynamodb_query_injection.js", - "filename": ".", - "source": { - "start": 32, - "end": 32, - "column": { - "start": 37, - "end": 61 - } - }, - "sink": { - "start": 32, - "end": 32, - "column": { - "start": 37, - "end": 61 - }, - "content": "new QueryCommand(params)" - }, - "parent_line_number": 32, - "snippet": "new QueryCommand(params)", - "fingerprint": "d3d9829e398dc3fa0b84684d1f8da7ef_2", - "old_fingerprint": "f80826420da7749a22d012e08e53f48f_2", - "code_extract": " const data = await ddbClient.send(new QueryCommand(params));" - } - ] -}" -`; - -exports[`javascript_third_parties_dynamodb_query_injection ok_no_injection 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/dynamodb_query_injection/test.js b/tests/javascript/third_parties/dynamodb_query_injection/test.js index a5c28ed89..bf2cedfff 100644 --- a/tests/javascript/third_parties/dynamodb_query_injection/test.js +++ b/tests/javascript/third_parties/dynamodb_query_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("dynamodb_query_injection", () => { + const testCase = "dynamodb_query_injection.js" + + const results = invoke(testCase) - test("dynamodb_query_injection", () => { - const testCase = "dynamodb_query_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_no_injection", () => { - const testCase = "ok_no_injection.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_no_injection", () => { + const testCase = "ok_no_injection.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/dynamodb_query_injection/testdata/dynamodb_query_injection.js b/tests/javascript/third_parties/dynamodb_query_injection/testdata/dynamodb_query_injection.js index f4d734cf1..3c2f6943a 100644 --- a/tests/javascript/third_parties/dynamodb_query_injection/testdata/dynamodb_query_injection.js +++ b/tests/javascript/third_parties/dynamodb_query_injection/testdata/dynamodb_query_injection.js @@ -7,6 +7,7 @@ const dynamodb = new DynamoDBClient({ region: "af-south-1" }) exports.handler = async function(event, _context) { const params = event["query_params"]; +// bearer:expected javascript_third_parties_dynamodb_query_injection const data = await ddbClient.send(new QueryCommand(params)); } @@ -15,6 +16,7 @@ var AWS = require('aws-sdk'); var docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-12-20'}); exports.handler = async function(event, _context) { +// bearer:expected javascript_third_parties_dynamodb_query_injection docClient.query(event["query"]["params"], function(err, data) {}); } @@ -29,5 +31,6 @@ exports.handler = async function(event, _context) { TableName: "BOOKS_TABLE", }; +// bearer:expected javascript_third_parties_dynamodb_query_injection const data = await ddbClient.send(new QueryCommand(params)); } \ No newline at end of file diff --git a/tests/javascript/third_parties/elasticsearch/__snapshots__/test.js.snap b/tests/javascript/third_parties/elasticsearch/__snapshots__/test.js.snap deleted file mode 100644 index fd8172126..000000000 --- a/tests/javascript/third_parties/elasticsearch/__snapshots__/test.js.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_elasticsearch insecure 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_elasticsearch", - "title": "Leakage of sensitive data to ElasticSearch", - "description": "## Description\\n\\nLeaking sensitive data to database is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to elasticsearch.\\n\\n## Remediations\\n\\n\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_elasticsearch", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 1, - "end": 1, - "column": { - "start": 16, - "end": 28 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 1, - "end": 26 - }, - "content": "elasticsearch.index(user)" - }, - "parent_line_number": 2, - "snippet": "elasticsearch.index(user)", - "fingerprint": "91c58f293b37db22fa297face0c007b3_0", - "old_fingerprint": "cc78d9104e7797c715a588bf45014ffc_0", - "code_extract": "elasticsearch.index(user);" - } - ] -}" -`; diff --git a/tests/javascript/third_parties/elasticsearch/test.js b/tests/javascript/third_parties/elasticsearch/test.js index 045e38ef2..399b2cc03 100644 --- a/tests/javascript/third_parties/elasticsearch/test.js +++ b/tests/javascript/third_parties/elasticsearch/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/elasticsearch/testdata/insecure.js b/tests/javascript/third_parties/elasticsearch/testdata/insecure.js index 6bdd005a7..7c4a59304 100644 --- a/tests/javascript/third_parties/elasticsearch/testdata/insecure.js +++ b/tests/javascript/third_parties/elasticsearch/testdata/insecure.js @@ -1,2 +1,3 @@ const user = { name: "jhon", email: "jhon@gmail.com" }; +// bearer:expected javascript_third_parties_elasticsearch elasticsearch.index(user); diff --git a/tests/javascript/third_parties/google_analytics/__snapshots__/test.js.snap b/tests/javascript/third_parties/google_analytics/__snapshots__/test.js.snap deleted file mode 100644 index 180f62030..000000000 --- a/tests/javascript/third_parties/google_analytics/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_google_analytics insecure 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_google_analytics", - "title": "Leakage of sensitive data to Google Analytics", - "description": "## Description\\n\\nLeaking sensitive data to third-party analytics tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Google Analytics.\\n\\n## Remediations\\n\\nWhen sending data to analytics libraries, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n gtag(\\"event\\", \\"screen_view\\", {\\n user: {\\n subscribed: true,\\n },\\n });\\n\`\`\`\\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/javascript_third_parties_google_analytics", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 3, - "end": 26 - } - }, - "sink": { - "start": 1, - "end": 5, - "column": { - "start": 1, - "end": 3 - }, - "content": "gtag(\\"event\\", \\"screen_view\\", {\\n\\tuser: {\\n\\t\\temail: \\"jhon@gmail.com\\",\\n\\t},\\n})" - }, - "parent_line_number": 1, - "snippet": "gtag(\\"event\\", \\"screen_view\\", {\\n\\tuser: {\\n\\t\\temail: \\"jhon@gmail.com\\",\\n\\t},\\n})", - "fingerprint": "50f052af0f997dae6751e3aa349aecf6_0", - "old_fingerprint": "4657d77eb63c00b706b210deab02e697_0", - "code_extract": "gtag(\\"event\\", \\"screen_view\\", {\\n\\tuser: {\\n\\t\\temail: \\"jhon@gmail.com\\",\\n\\t},\\n});" - } - ] -}" -`; - -exports[`javascript_third_parties_google_analytics secure 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/google_analytics/test.js b/tests/javascript/third_parties/google_analytics/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/third_parties/google_analytics/test.js +++ b/tests/javascript/third_parties/google_analytics/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/google_analytics/testdata/insecure.js b/tests/javascript/third_parties/google_analytics/testdata/insecure.js index 05a5e8e4a..f2cc718a4 100644 --- a/tests/javascript/third_parties/google_analytics/testdata/insecure.js +++ b/tests/javascript/third_parties/google_analytics/testdata/insecure.js @@ -1,3 +1,4 @@ +// bearer:expected javascript_third_parties_google_analytics gtag("event", "screen_view", { user: { email: "jhon@gmail.com", diff --git a/tests/javascript/third_parties/google_tag_manager/__snapshots__/test.js.snap b/tests/javascript/third_parties/google_tag_manager/__snapshots__/test.js.snap deleted file mode 100644 index 93d682554..000000000 --- a/tests/javascript/third_parties/google_tag_manager/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_google_tag_manager insecure 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_google_tag_manager", - "title": "Leakage of sensitive data to Google Tag Manager", - "description": "## Description\\n\\nLeaking sensitive data to third parties is a common cause of data leaks and can lead to data breaches. This rule looks for instances of leaking sensitive data to third parties using google tag manager.\\n\\n❌ Avoid sending sensitive data to third parties:\\n\\n\`\`\`javascript\\ndatalayer.push({\\n user: {\\n email: user.email\\n }\\n})\\n\`\`\`\\n\\n✅ If you need to identify a user, ensure to use their unique identifier instead of their personal identifiable information:\\n\\n\`\`\`javascript\\ndatalayer.push({\\n user: {\\n uuid: user.uuid\\n }\\n})\\n\`\`\`\\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/javascript_third_parties_google_tag_manager", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 4, - "end": 4, - "column": { - "start": 9, - "end": 19 - } - }, - "sink": { - "start": 3, - "end": 5, - "column": { - "start": 1, - "end": 3 - }, - "content": "window.dataLayer.push({\\n\\temail: user.email,\\n})" - }, - "parent_line_number": 3, - "snippet": "window.dataLayer.push({\\n\\temail: user.email,\\n})", - "fingerprint": "da9f822205740bd5ee47f56b7ebccf6e_0", - "old_fingerprint": "97bc915b9ebfbb946bad920a01e4def5_0", - "code_extract": "window.dataLayer.push({\\n\\temail: user.email,\\n});" - } - ] -}" -`; - -exports[`javascript_third_parties_google_tag_manager secure 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/google_tag_manager/test.js b/tests/javascript/third_parties/google_tag_manager/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/third_parties/google_tag_manager/test.js +++ b/tests/javascript/third_parties/google_tag_manager/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/google_tag_manager/testdata/insecure.js b/tests/javascript/third_parties/google_tag_manager/testdata/insecure.js index efcaf51f3..e20e170df 100644 --- a/tests/javascript/third_parties/google_tag_manager/testdata/insecure.js +++ b/tests/javascript/third_parties/google_tag_manager/testdata/insecure.js @@ -1,5 +1,6 @@ const user = { email: "jhon@gmail.com" }; +// bearer:expected javascript_third_parties_google_tag_manager window.dataLayer.push({ email: user.email, }); diff --git a/tests/javascript/third_parties/honeybadger/__snapshots__/test.js.snap b/tests/javascript/third_parties/honeybadger/__snapshots__/test.js.snap deleted file mode 100644 index 8603754fa..000000000 --- a/tests/javascript/third_parties/honeybadger/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_honeybadger insecure 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_honeybadger", - "title": "Leakage of sensitive data to HoneyBadget", - "description": "## Description\\n\\nLeaking sensitive data to third-party error logging tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Honeybadger.\\n\\n## Remediations\\n\\nWhen sending data to logging libraries, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n const Honeybadger = require(\\"@honeybadger-io/js\\");\\n\\n let context = { user: { uuid: \\"aacd05fd-8f5b-4bc6-aa8b-35e5fbf37325\\" } };\\n\\n Honeybadger.setContext(context);\\n\`\`\`\\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/javascript_third_parties_honeybadger", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 25, - "end": 48 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 32 - }, - "content": "Honeybadger.setContext(context)" - }, - "parent_line_number": 5, - "snippet": "Honeybadger.setContext(context)", - "fingerprint": "b951d3bbde6630fbf6e50c52b01dc701_0", - "old_fingerprint": "ffe206430d05c27ca79209b5765ccbd0_0", - "code_extract": "Honeybadger.setContext(context);" - } - ] -}" -`; - -exports[`javascript_third_parties_honeybadger secure 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/honeybadger/test.js b/tests/javascript/third_parties/honeybadger/test.js index 1f685d106..4e4f1f51a 100644 --- a/tests/javascript/third_parties/honeybadger/test.js +++ b/tests/javascript/third_parties/honeybadger/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("secure", () => { - const testCase = "secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("secure", () => { + const testCase = "secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/honeybadger/testdata/insecure.js b/tests/javascript/third_parties/honeybadger/testdata/insecure.js index 649eeade0..193059f0b 100644 --- a/tests/javascript/third_parties/honeybadger/testdata/insecure.js +++ b/tests/javascript/third_parties/honeybadger/testdata/insecure.js @@ -2,4 +2,5 @@ const Honeybadger = require("@honeybadger-io/js"); let context = { user: { email: "jhon@gmail.com" } }; +// bearer:expected javascript_third_parties_honeybadger Honeybadger.setContext(context); diff --git a/tests/javascript/third_parties/new_relic/__snapshots__/test.js.snap b/tests/javascript/third_parties/new_relic/__snapshots__/test.js.snap deleted file mode 100644 index 36aae2857..000000000 --- a/tests/javascript/third_parties/new_relic/__snapshots__/test.js.snap +++ /dev/null @@ -1,242 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_new_relic datatype_in_interaction_set_attribute 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_new_relic", - "title": "Leakage of sensitive data to New Relic", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to New Relic.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [New Relic Docs](https://docs.newrelic.com/)\\n- [Log obfuscation](https://docs.newrelic.com/docs/logs/ui-data/obfuscation-ui/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_new_relic", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/datatype_in_interaction_set_attribute.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Firstname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 6, - "end": 6, - "column": { - "start": 31, - "end": 46 - } - }, - "sink": { - "start": 5, - "end": 6, - "column": { - "start": 3, - "end": 47 - }, - "content": "newrelic.interaction()\\n .setAttribute(\\"username\\", user.first_name)" - }, - "parent_line_number": 5, - "snippet": "newrelic.interaction()\\n .setAttribute(\\"username\\", user.first_name)", - "fingerprint": "63161101404765527f0dada7fd00b64e_0", - "old_fingerprint": "d4a33ef10c96118848e50cbe6babe62c_0", - "code_extract": " newrelic.interaction()\\n .setAttribute(\\"username\\", user.first_name)" - }, - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_new_relic", - "title": "Leakage of sensitive data to New Relic", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to New Relic.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [New Relic Docs](https://docs.newrelic.com/)\\n- [Log obfuscation](https://docs.newrelic.com/docs/logs/ui-data/obfuscation-ui/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_new_relic", - "line_number": 13, - "full_filename": "/tmp/bearer-scan/datatype_in_interaction_set_attribute.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 13, - "end": 13, - "column": { - "start": 35, - "end": 53 - } - }, - "sink": { - "start": 13, - "end": 13, - "column": { - "start": 1, - "end": 54 - }, - "content": "interaction.setAttribute(\\"email\\", user.email_address)" - }, - "parent_line_number": 13, - "snippet": "interaction.setAttribute(\\"email\\", user.email_address)", - "fingerprint": "63161101404765527f0dada7fd00b64e_2", - "old_fingerprint": "d4a33ef10c96118848e50cbe6babe62c_2", - "code_extract": "interaction.setAttribute(\\"email\\", user.email_address)" - } - ] -}" -`; - -exports[`javascript_third_parties_new_relic datatype_in_notice_error 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_new_relic", - "title": "Leakage of sensitive data to New Relic", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to New Relic.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [New Relic Docs](https://docs.newrelic.com/)\\n- [Log obfuscation](https://docs.newrelic.com/docs/logs/ui-data/obfuscation-ui/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_new_relic", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/datatype_in_notice_error.js", - "filename": ".", - "data_type": { - "category_uuid": "b5a3b0fd-dd5c-420d-91ce-dd2dddc8cc38", - "name": "IP address" - }, - "category_groups": [ - "Personal Data" - ], - "source": { - "start": 7, - "end": 7, - "column": { - "start": 31, - "end": 50 - } - }, - "sink": { - "start": 7, - "end": 7, - "column": { - "start": 5, - "end": 51 - }, - "content": "newrelic.noticeError(err, customer.ip_address)" - }, - "parent_line_number": 7, - "snippet": "newrelic.noticeError(err, customer.ip_address)", - "fingerprint": "63161101404765527f0dada7fd00b64e_0", - "old_fingerprint": "cf5937bc41ef8e6cf874e0326f3da03e_0", - "code_extract": " newrelic.noticeError(err, customer.ip_address)" - } - ] -}" -`; - -exports[`javascript_third_parties_new_relic datatype_in_set_custom_attribute 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_new_relic", - "title": "Leakage of sensitive data to New Relic", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to New Relic.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [New Relic Docs](https://docs.newrelic.com/)\\n- [Log obfuscation](https://docs.newrelic.com/docs/logs/ui-data/obfuscation-ui/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_new_relic", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/datatype_in_set_custom_attribute.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 40, - "end": 54 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 55 - }, - "content": "newrelic.setCustomAttribute(\\"user-id\\", customer.email)" - }, - "parent_line_number": 3, - "snippet": "newrelic.setCustomAttribute(\\"user-id\\", customer.email)", - "fingerprint": "63161101404765527f0dada7fd00b64e_0", - "old_fingerprint": "04e609e85c5a7c6ca13e1b88df45e81f_0", - "code_extract": "newrelic.setCustomAttribute(\\"user-id\\", customer.email)" - } - ] -}" -`; - -exports[`javascript_third_parties_new_relic datatype_in_set_page_view_name 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_new_relic", - "title": "Leakage of sensitive data to New Relic", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to New Relic.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [New Relic Docs](https://docs.newrelic.com/)\\n- [Log obfuscation](https://docs.newrelic.com/docs/logs/ui-data/obfuscation-ui/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_new_relic", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/datatype_in_set_page_view_name.js", - "filename": ".", - "data_type": { - "category_uuid": "7a794bd6-a6d1-429d-91a2-377acce9e9db", - "name": "Bank Account" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 3, - "end": 3, - "column": { - "start": 26, - "end": 54 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 64 - }, - "content": "newrelic.setPageViewName(customer.bank_account_number, \\"$host\\")" - }, - "parent_line_number": 3, - "snippet": "newrelic.setPageViewName(customer.bank_account_number, \\"$host\\")", - "fingerprint": "63161101404765527f0dada7fd00b64e_0", - "old_fingerprint": "16039f64b7a3f77ef2f016652ce21d1f_0", - "code_extract": "newrelic.setPageViewName(customer.bank_account_number, \\"$host\\")" - } - ] -}" -`; - -exports[`javascript_third_parties_new_relic ok_ignored_datatypes_only 1`] = `"{}"`; - -exports[`javascript_third_parties_new_relic ok_no_datatypes 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/new_relic/test.js b/tests/javascript/third_parties/new_relic/test.js index ea2f812f8..cc77b5ddf 100644 --- a/tests/javascript/third_parties/new_relic/test.js +++ b/tests/javascript/third_parties/new_relic/test.js @@ -1,43 +1,70 @@ -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("datatype_in_interaction_set_attribute", () => { + const testCase = "datatype_in_interaction_set_attribute.js" + + const results = invoke(testCase) - test("datatype_in_interaction_set_attribute", () => { - const testCase = "datatype_in_interaction_set_attribute.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_notice_error", () => { - const testCase = "datatype_in_notice_error.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_notice_error", () => { + const testCase = "datatype_in_notice_error.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_set_custom_attribute", () => { - const testCase = "datatype_in_set_custom_attribute.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_set_custom_attribute", () => { + const testCase = "datatype_in_set_custom_attribute.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_set_page_view_name", () => { - const testCase = "datatype_in_set_page_view_name.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_set_page_view_name", () => { + const testCase = "datatype_in_set_page_view_name.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_ignored_datatypes_only", () => { - const testCase = "ok_ignored_datatypes_only.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_ignored_datatypes_only", () => { + const testCase = "ok_ignored_datatypes_only.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_no_datatypes", () => { - const testCase = "ok_no_datatypes.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_no_datatypes", () => { + const testCase = "ok_no_datatypes.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/new_relic/testdata/datatype_in_interaction_set_attribute.js b/tests/javascript/third_parties/new_relic/testdata/datatype_in_interaction_set_attribute.js index 6d75ee74f..b632e9bb3 100644 --- a/tests/javascript/third_parties/new_relic/testdata/datatype_in_interaction_set_attribute.js +++ b/tests/javascript/third_parties/new_relic/testdata/datatype_in_interaction_set_attribute.js @@ -2,6 +2,7 @@ const newrelic = require("newrelic") router.addRoute("/order", () => { const user = getCurrentUser(); +// bearer:expected javascript_third_parties_new_relic newrelic.interaction() .setAttribute("username", user.first_name) .setAttribute("postal-code", user.post_code); @@ -10,4 +11,5 @@ router.addRoute("/order", () => { // alternative syntax var interaction = newrelic.interaction() +// bearer:expected javascript_third_parties_new_relic interaction.setAttribute("email", user.email_address) \ No newline at end of file diff --git a/tests/javascript/third_parties/new_relic/testdata/datatype_in_notice_error.js b/tests/javascript/third_parties/new_relic/testdata/datatype_in_notice_error.js index 388394174..75ac6852e 100644 --- a/tests/javascript/third_parties/new_relic/testdata/datatype_in_notice_error.js +++ b/tests/javascript/third_parties/new_relic/testdata/datatype_in_notice_error.js @@ -4,6 +4,7 @@ someFunc(() => { try { // something } catch (err){ +// bearer:expected javascript_third_parties_new_relic newrelic.noticeError(err, customer.ip_address) } }) \ No newline at end of file diff --git a/tests/javascript/third_parties/new_relic/testdata/datatype_in_set_custom_attribute.js b/tests/javascript/third_parties/new_relic/testdata/datatype_in_set_custom_attribute.js index f52bf8745..7b4f78a57 100644 --- a/tests/javascript/third_parties/new_relic/testdata/datatype_in_set_custom_attribute.js +++ b/tests/javascript/third_parties/new_relic/testdata/datatype_in_set_custom_attribute.js @@ -1,3 +1,4 @@ const newrelic = require("newrelic") +// bearer:expected javascript_third_parties_new_relic newrelic.setCustomAttribute("user-id", customer.email) diff --git a/tests/javascript/third_parties/new_relic/testdata/datatype_in_set_page_view_name.js b/tests/javascript/third_parties/new_relic/testdata/datatype_in_set_page_view_name.js index 9e23fbc7f..1312c6f28 100644 --- a/tests/javascript/third_parties/new_relic/testdata/datatype_in_set_page_view_name.js +++ b/tests/javascript/third_parties/new_relic/testdata/datatype_in_set_page_view_name.js @@ -1,3 +1,4 @@ const newrelic = require('newrelic') +// bearer:expected javascript_third_parties_new_relic newrelic.setPageViewName(customer.bank_account_number, "$host") diff --git a/tests/javascript/third_parties/open_telemetry/__snapshots__/test.js.snap b/tests/javascript/third_parties/open_telemetry/__snapshots__/test.js.snap deleted file mode 100644 index 857b4d450..000000000 --- a/tests/javascript/third_parties/open_telemetry/__snapshots__/test.js.snap +++ /dev/null @@ -1,240 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_open_telemetry datatype_in_add_event 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_open_telemetry", - "title": "Leakage of sensitive data to Open Telemetry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Open Telemetry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Open Telemetry Docs](https://opentelemetry.io/docs/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_open_telemetry", - "line_number": 4, - "full_filename": "/tmp/bearer-scan/datatype_in_add_event.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 5, - "end": 5, - "column": { - "start": 21, - "end": 42 - } - }, - "sink": { - "start": 4, - "end": 6, - "column": { - "start": 1, - "end": 3 - }, - "content": "currentSpan.addEvent('my-event', {\\n 'event.metadata': customer.emailAddress\\n})" - }, - "parent_line_number": 4, - "snippet": "currentSpan.addEvent('my-event', {\\n 'event.metadata': customer.emailAddress\\n})", - "fingerprint": "cd48423a5a7a06612fb15c8b7045814c_0", - "old_fingerprint": "61188f2f3df9254f0d28be6f2c03f687_0", - "code_extract": "currentSpan.addEvent('my-event', {\\n 'event.metadata': customer.emailAddress\\n})" - } - ] -}" -`; - -exports[`javascript_third_parties_open_telemetry datatype_in_record_exception 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_open_telemetry", - "title": "Leakage of sensitive data to Open Telemetry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Open Telemetry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Open Telemetry Docs](https://opentelemetry.io/docs/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_open_telemetry", - "line_number": 9, - "full_filename": "/tmp/bearer-scan/datatype_in_record_exception.js", - "filename": ".", - "data_type": { - "category_uuid": "b5a3b0fd-dd5c-420d-91ce-dd2dddc8cc38", - "name": "IP address" - }, - "category_groups": [ - "Personal Data" - ], - "source": { - "start": 9, - "end": 9, - "column": { - "start": 24, - "end": 45 - } - }, - "sink": { - "start": 9, - "end": 9, - "column": { - "start": 3, - "end": 46 - }, - "content": "span.recordException(currentUser.ipAddress)" - }, - "parent_line_number": 9, - "snippet": "span.recordException(currentUser.ipAddress)", - "fingerprint": "cd48423a5a7a06612fb15c8b7045814c_0", - "old_fingerprint": "b722ff54510aa26ac8f0ecf64037d639_0", - "code_extract": " span.recordException(currentUser.ipAddress)" - } - ] -}" -`; - -exports[`javascript_third_parties_open_telemetry datatype_in_set_attribute 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_open_telemetry", - "title": "Leakage of sensitive data to Open Telemetry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Open Telemetry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Open Telemetry Docs](https://opentelemetry.io/docs/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_open_telemetry", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/datatype_in_set_attribute.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 6, - "end": 6, - "column": { - "start": 37, - "end": 61 - } - }, - "sink": { - "start": 6, - "end": 6, - "column": { - "start": 3, - "end": 62 - }, - "content": "span.setAttribute(\\"current-user\\", currentUser.emailAddress)" - }, - "parent_line_number": 6, - "snippet": "span.setAttribute(\\"current-user\\", currentUser.emailAddress)", - "fingerprint": "cd48423a5a7a06612fb15c8b7045814c_0", - "old_fingerprint": "46c63d278ec3bb5452fcbdf1305375ae_0", - "code_extract": " span.setAttribute(\\"current-user\\", currentUser.emailAddress);" - }, - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_open_telemetry", - "title": "Leakage of sensitive data to Open Telemetry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Open Telemetry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Open Telemetry Docs](https://opentelemetry.io/docs/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_open_telemetry", - "line_number": 11, - "full_filename": "/tmp/bearer-scan/datatype_in_set_attribute.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 11, - "end": 11, - "column": { - "start": 35, - "end": 45 - } - }, - "sink": { - "start": 11, - "end": 11, - "column": { - "start": 1, - "end": 46 - }, - "content": "span.setAttribute(\\"current-user\\", user.email)" - }, - "parent_line_number": 11, - "snippet": "span.setAttribute(\\"current-user\\", user.email)", - "fingerprint": "cd48423a5a7a06612fb15c8b7045814c_1", - "old_fingerprint": "46c63d278ec3bb5452fcbdf1305375ae_1", - "code_extract": "span.setAttribute(\\"current-user\\", user.email);" - } - ] -}" -`; - -exports[`javascript_third_parties_open_telemetry datatype_in_set_status 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_open_telemetry", - "title": "Leakage of sensitive data to Open Telemetry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Open Telemetry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Open Telemetry Docs](https://opentelemetry.io/docs/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_open_telemetry", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/datatype_in_set_status.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 9, - "end": 9, - "column": { - "start": 40, - "end": 64 - } - }, - "sink": { - "start": 7, - "end": 10, - "column": { - "start": 5, - "end": 7 - }, - "content": "span.setStatus({\\n code: opentelemetry.SpanStatusCode.ERROR,\\n message: \\"Bad connection for \\" + currentUser.emailAddress\\n })" - }, - "parent_line_number": 7, - "snippet": "span.setStatus({\\n code: opentelemetry.SpanStatusCode.ERROR,\\n message: \\"Bad connection for \\" + currentUser.emailAddress\\n })", - "fingerprint": "cd48423a5a7a06612fb15c8b7045814c_0", - "old_fingerprint": "b455b6a052b93860acda04124875787e_0", - "code_extract": " span.setStatus({\\n code: opentelemetry.SpanStatusCode.ERROR,\\n message: \\"Bad connection for \\" + currentUser.emailAddress\\n })" - } - ] -}" -`; - -exports[`javascript_third_parties_open_telemetry ok_no_datatypes 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/open_telemetry/test.js b/tests/javascript/third_parties/open_telemetry/test.js index 2c50d1758..47b00969a 100644 --- a/tests/javascript/third_parties/open_telemetry/test.js +++ b/tests/javascript/third_parties/open_telemetry/test.js @@ -1,37 +1,60 @@ -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("datatype_in_add_event", () => { + const testCase = "datatype_in_add_event.js" + + const results = invoke(testCase) - test("datatype_in_add_event", () => { - const testCase = "datatype_in_add_event.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_record_exception", () => { - const testCase = "datatype_in_record_exception.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_record_exception", () => { + const testCase = "datatype_in_record_exception.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_set_attribute", () => { - const testCase = "datatype_in_set_attribute.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_set_attribute", () => { + const testCase = "datatype_in_set_attribute.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_set_status", () => { - const testCase = "datatype_in_set_status.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_set_status", () => { + const testCase = "datatype_in_set_status.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_no_datatypes", () => { - const testCase = "ok_no_datatypes.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_no_datatypes", () => { + const testCase = "ok_no_datatypes.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_add_event.js b/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_add_event.js index 279a7ee8c..084da4bd6 100644 --- a/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_add_event.js +++ b/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_add_event.js @@ -1,6 +1,7 @@ import * as opentelemetry from "@opentelemetry/sdk-node" var currentSpan = opentelemetry.trace.getSpan() +// bearer:expected javascript_third_parties_open_telemetry currentSpan.addEvent('my-event', { 'event.metadata': customer.emailAddress }) diff --git a/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_record_exception.js b/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_record_exception.js index eae7d3a11..045909d4e 100644 --- a/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_record_exception.js +++ b/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_record_exception.js @@ -6,5 +6,6 @@ try { // something } catch (err) { span.recordException(err) +// bearer:expected javascript_third_parties_open_telemetry span.recordException(currentUser.ipAddress) } \ No newline at end of file diff --git a/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_set_attribute.js b/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_set_attribute.js index e3e2c98fb..e830310fe 100644 --- a/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_set_attribute.js +++ b/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_set_attribute.js @@ -3,9 +3,11 @@ import * as opentelemetry from "@opentelemetry/sdk-node" const tracer = opentelemetry.trace.getTracer("some-tracer"); tracer.startActiveSpan("some-span", span => { +// bearer:expected javascript_third_parties_open_telemetry span.setAttribute("current-user", currentUser.emailAddress); span.end(); }); +// bearer:expected javascript_third_parties_open_telemetry span.setAttribute("current-user", user.email); diff --git a/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_set_status.js b/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_set_status.js index e8a0d2d83..12139b549 100644 --- a/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_set_status.js +++ b/tests/javascript/third_parties/open_telemetry/testdata/datatype_in_set_status.js @@ -4,6 +4,7 @@ const tracer = opentelemetry.trace.getTracer("some-tracer"); tracer.startActiveSpan("app.some-span", { attributes: { name: currentUser.name } }, span => { if (somethingWentWrong()) { +// bearer:expected javascript_third_parties_open_telemetry span.setStatus({ code: opentelemetry.SpanStatusCode.ERROR, message: "Bad connection for " + currentUser.emailAddress diff --git a/tests/javascript/third_parties/openai/__snapshots__/test.js.snap b/tests/javascript/third_parties/openai/__snapshots__/test.js.snap deleted file mode 100644 index ff25e4b8f..000000000 --- a/tests/javascript/third_parties/openai/__snapshots__/test.js.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_openai insecure 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_openai", - "title": "Leakage of sensitive data to OpenAI", - "description": "## Description\\nLeaking sensitive data to third-party is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to OpenAI.\\n\\n## Remediations\\n\\nWhen using a third-party, ensure all sensitive data is removed.\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_openai", - "line_number": 8, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 10, - "end": 10, - "column": { - "start": 26, - "end": 36 - } - }, - "sink": { - "start": 8, - "end": 11, - "column": { - "start": 26, - "end": 3 - }, - "content": "openai.createCompletion({\\n model: \\"text-davinci-003\\",\\n prompt: \`Hello world \${user.email}\`,\\n})" - }, - "parent_line_number": 8, - "snippet": "openai.createCompletion({\\n model: \\"text-davinci-003\\",\\n prompt: \`Hello world \${user.email}\`,\\n})", - "fingerprint": "5bb06b54684897680375ebb1559bacfd_0", - "old_fingerprint": "13b565e880e29c576c454fa1935f87ea_0", - "code_extract": "const completion = await openai.createCompletion({\\n model: \\"text-davinci-003\\",\\n prompt: \`Hello world \${user.email}\`,\\n})" - } - ] -}" -`; diff --git a/tests/javascript/third_parties/openai/test.js b/tests/javascript/third_parties/openai/test.js index 045e38ef2..399b2cc03 100644 --- a/tests/javascript/third_parties/openai/test.js +++ b/tests/javascript/third_parties/openai/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/openai/testdata/insecure.js b/tests/javascript/third_parties/openai/testdata/insecure.js index 563a30ad1..0b690fd6f 100644 --- a/tests/javascript/third_parties/openai/testdata/insecure.js +++ b/tests/javascript/third_parties/openai/testdata/insecure.js @@ -5,6 +5,7 @@ const configuration = new Configuration({ }) const openai = new OpenAIApi(configuration) +// bearer:expected javascript_third_parties_openai const completion = await openai.createCompletion({ model: "text-davinci-003", prompt: `Hello world ${user.email}`, diff --git a/tests/javascript/third_parties/passport_hardcoded_secret/__snapshots__/test.js.snap b/tests/javascript/third_parties/passport_hardcoded_secret/__snapshots__/test.js.snap deleted file mode 100644 index 77a65d26e..000000000 --- a/tests/javascript/third_parties/passport_hardcoded_secret/__snapshots__/test.js.snap +++ /dev/null @@ -1,42 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_passport_hardcoded_secret insecure 1`] = ` -"{ - "high": [ - { - "cwe_ids": [ - "798" - ], - "id": "javascript_third_parties_passport_hardcoded_secret", - "title": "Usage of hard-coded passport secret", - "description": "## Description\\n\\nCode is not a safe place to store secrets, use environment variables instead.\\n\\n## Remediations\\n\\nUse environment variables instead\\n\\n\`\`\`javascript\\n const strategy = new GoogleStrategy({ clientSecret: process.ENV.GOOGLE_SECRET });\\n passport.use(strategy);\\n\`\`\`\\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/javascript_third_parties_passport_hardcoded_secret", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/insecure.js", - "filename": ".", - "source": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 23 - } - }, - "sink": { - "start": 5, - "end": 5, - "column": { - "start": 1, - "end": 23 - }, - "content": "passport.use(strategy)" - }, - "parent_line_number": 5, - "snippet": "passport.use(strategy)", - "fingerprint": "998181c239ce6c5a9107eb9c5902c667_0", - "old_fingerprint": "cd9533ab143105896e7edf76e3426f28_0", - "code_extract": "passport.use(strategy);" - } - ] -}" -`; diff --git a/tests/javascript/third_parties/passport_hardcoded_secret/test.js b/tests/javascript/third_parties/passport_hardcoded_secret/test.js index 045e38ef2..399b2cc03 100644 --- a/tests/javascript/third_parties/passport_hardcoded_secret/test.js +++ b/tests/javascript/third_parties/passport_hardcoded_secret/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("insecure", () => { + const testCase = "insecure.js" + + const results = invoke(testCase) - test("insecure", () => { - const testCase = "insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/passport_hardcoded_secret/testdata/insecure.js b/tests/javascript/third_parties/passport_hardcoded_secret/testdata/insecure.js index dfec43a4c..74370ac2f 100644 --- a/tests/javascript/third_parties/passport_hardcoded_secret/testdata/insecure.js +++ b/tests/javascript/third_parties/passport_hardcoded_secret/testdata/insecure.js @@ -2,4 +2,5 @@ const GoogleStrategy = require("passport-google-oauth").Strategy; const passport = require("passport"); const strategy = new GoogleStrategy({ clientSecret: "hardcodedSecret" }); +// bearer:expected javascript_third_parties_passport_hardcoded_secret passport.use(strategy); diff --git a/tests/javascript/third_parties/rollbar/__snapshots__/test.js.snap b/tests/javascript/third_parties/rollbar/__snapshots__/test.js.snap deleted file mode 100644 index bdec0192b..000000000 --- a/tests/javascript/third_parties/rollbar/__snapshots__/test.js.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_rollbar browser_insecure 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_rollbar", - "title": "Leakage of sensitive data to RollBar", - "description": "## Description\\n\\nLeaking sensitive data to third-party error logging tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Rollbar.\\n\\n## Remediations\\n\\nWhen sending data to logging libraries, ensure all sensitive data is removed.\\n\\nIf you really need to identify users, use unique identifiers from the database.\\n\\n\`\`\`javascript\\n Rollbar.critical(\\"Connection error from remote Payments API\\", user.uuid);\\n\`\`\`\\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/javascript_third_parties_rollbar", - "line_number": 3, - "full_filename": "/tmp/bearer-scan/browser_insecure.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 1, - "end": 1, - "column": { - "start": 16, - "end": 28 - } - }, - "sink": { - "start": 3, - "end": 3, - "column": { - "start": 1, - "end": 68 - }, - "content": "Rollbar.critical(\\"Connection error from remote Payments API\\", user)" - }, - "parent_line_number": 3, - "snippet": "Rollbar.critical(\\"Connection error from remote Payments API\\", user)", - "fingerprint": "550f52afa2d5c58ba3d7c0686d5fb696_0", - "old_fingerprint": "3754a72a6068ba10038717ffc426f823_0", - "code_extract": "Rollbar.critical(\\"Connection error from remote Payments API\\", user);" - } - ] -}" -`; - -exports[`javascript_third_parties_rollbar browser_secure 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/rollbar/test.js b/tests/javascript/third_parties/rollbar/test.js index 8140a1c54..90e2c1b2f 100644 --- a/tests/javascript/third_parties/rollbar/test.js +++ b/tests/javascript/third_parties/rollbar/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("browser_insecure", () => { + const testCase = "browser_insecure.js" + + const results = invoke(testCase) - test("browser_insecure", () => { - const testCase = "browser_insecure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("browser_secure", () => { - const testCase = "browser_secure.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("browser_secure", () => { + const testCase = "browser_secure.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/rollbar/testdata/browser_insecure.js b/tests/javascript/third_parties/rollbar/testdata/browser_insecure.js index 2352cca1f..6f85e4640 100644 --- a/tests/javascript/third_parties/rollbar/testdata/browser_insecure.js +++ b/tests/javascript/third_parties/rollbar/testdata/browser_insecure.js @@ -1,3 +1,4 @@ const user = { name: "jhon", email: "jhon@gmail.com" }; +// bearer:expected javascript_third_parties_rollbar Rollbar.critical("Connection error from remote Payments API", user); diff --git a/tests/javascript/third_parties/segment/__snapshots__/test.js.snap b/tests/javascript/third_parties/segment/__snapshots__/test.js.snap deleted file mode 100644 index 1b719d1cb..000000000 --- a/tests/javascript/third_parties/segment/__snapshots__/test.js.snap +++ /dev/null @@ -1,333 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_segment datatype_in_alias 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_segment", - "title": "Leakage of sensitive data to Segment", - "description": "## Description\\nLeaking sensitive data to third-party analytics tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Segment.\\n\\n## Remediations\\n\\nWhen sending data to analytics libraries, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Segment Node.js docs](https://segment.com/docs/connections/sources/catalog/libraries/server/node/)\\n- [Segment JavaScript docs](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_segment", - "line_number": 7, - "full_filename": "/tmp/bearer-scan/datatype_in_alias.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 8, - "end": 8, - "column": { - "start": 15, - "end": 25 - } - }, - "sink": { - "start": 7, - "end": 10, - "column": { - "start": 1, - "end": 3 - }, - "content": "appAnalytics.alias({\\n previousId: user.email,\\n userId: user.id,\\n})" - }, - "parent_line_number": 7, - "snippet": "appAnalytics.alias({\\n previousId: user.email,\\n userId: user.id,\\n})", - "fingerprint": "df462286e9e34d817b61a361c26e8720_0", - "old_fingerprint": "db340be69ed775c0191d246a49a09329_0", - "code_extract": "appAnalytics.alias({\\n previousId: user.email,\\n userId: user.id,\\n});" - } - ] -}" -`; - -exports[`javascript_third_parties_segment datatype_in_group 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_segment", - "title": "Leakage of sensitive data to Segment", - "description": "## Description\\nLeaking sensitive data to third-party analytics tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Segment.\\n\\n## Remediations\\n\\nWhen sending data to analytics libraries, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Segment Node.js docs](https://segment.com/docs/connections/sources/catalog/libraries/server/node/)\\n- [Segment JavaScript docs](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_segment", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/datatype_in_group.js", - "filename": ".", - "data_type": { - "category_uuid": "ef613213-a222-4c01-ae38-c3043b68f738", - "name": "Job Titles" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 8, - "end": 8, - "column": { - "start": 12, - "end": 26 - } - }, - "sink": { - "start": 6, - "end": 10, - "column": { - "start": 1, - "end": 3 - }, - "content": "analytics.group({\\n userId: user.id,\\n groupId: user.job_title,\\n traits: {},\\n})" - }, - "parent_line_number": 6, - "snippet": "analytics.group({\\n userId: user.id,\\n groupId: user.job_title,\\n traits: {},\\n})", - "fingerprint": "df462286e9e34d817b61a361c26e8720_0", - "old_fingerprint": "8a1109dfe8fc062a4e1155a216bb8914_0", - "code_extract": "analytics.group({\\n userId: user.id,\\n groupId: user.job_title,\\n traits: {},\\n});" - } - ] -}" -`; - -exports[`javascript_third_parties_segment datatype_in_identify 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_segment", - "title": "Leakage of sensitive data to Segment", - "description": "## Description\\nLeaking sensitive data to third-party analytics tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Segment.\\n\\n## Remediations\\n\\nWhen sending data to analytics libraries, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Segment Node.js docs](https://segment.com/docs/connections/sources/catalog/libraries/server/node/)\\n- [Segment JavaScript docs](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_segment", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/datatype_in_identify.js", - "filename": ".", - "data_type": { - "category_uuid": "14124881-6b92-4fc5-8005-ea7c1c09592e", - "name": "Fullname" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 8, - "end": 8, - "column": { - "start": 5, - "end": 24 - } - }, - "sink": { - "start": 5, - "end": 13, - "column": { - "start": 1, - "end": 3 - }, - "content": "analytics.identify({\\n userId: user.id,\\n traits: {\\n name: user.fullName,\\n email: user.emailAddress,\\n plan: user.businessPlan,\\n friends: user.friendCount\\n }\\n})" - }, - "parent_line_number": 5, - "snippet": "analytics.identify({\\n userId: user.id,\\n traits: {\\n name: user.fullName,\\n email: user.emailAddress,\\n plan: user.businessPlan,\\n friends: user.friendCount\\n }\\n})", - "fingerprint": "df462286e9e34d817b61a361c26e8720_0", - "old_fingerprint": "cb032b072d0a7bcaf1ca43e2bdc2b5cb_0", - "code_extract": "analytics.identify({\\n userId: user.id,\\n traits: {\\n name: user.fullName,\\n email: user.emailAddress,\\n plan: user.businessPlan,\\n friends: user.friendCount\\n }\\n});" - }, - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_segment", - "title": "Leakage of sensitive data to Segment", - "description": "## Description\\nLeaking sensitive data to third-party analytics tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Segment.\\n\\n## Remediations\\n\\nWhen sending data to analytics libraries, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Segment Node.js docs](https://segment.com/docs/connections/sources/catalog/libraries/server/node/)\\n- [Segment JavaScript docs](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_segment", - "line_number": 18, - "full_filename": "/tmp/bearer-scan/datatype_in_identify.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 18, - "end": 18, - "column": { - "start": 18, - "end": 28 - } - }, - "sink": { - "start": 18, - "end": 18, - "column": { - "start": 1, - "end": 29 - }, - "content": "browser.identify(user.email)" - }, - "parent_line_number": 18, - "snippet": "browser.identify(user.email)", - "fingerprint": "df462286e9e34d817b61a361c26e8720_3", - "old_fingerprint": "cb032b072d0a7bcaf1ca43e2bdc2b5cb_3", - "code_extract": "browser.identify(user.email)" - } - ] -}" -`; - -exports[`javascript_third_parties_segment datatype_in_page 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_segment", - "title": "Leakage of sensitive data to Segment", - "description": "## Description\\nLeaking sensitive data to third-party analytics tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Segment.\\n\\n## Remediations\\n\\nWhen sending data to analytics libraries, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Segment Node.js docs](https://segment.com/docs/connections/sources/catalog/libraries/server/node/)\\n- [Segment JavaScript docs](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_segment", - "line_number": 6, - "full_filename": "/tmp/bearer-scan/datatype_in_page.js", - "filename": ".", - "data_type": { - "category_uuid": "7a794bd6-a6d1-429d-91a2-377acce9e9db", - "name": "Bank Account" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 10, - "end": 10, - "column": { - "start": 20, - "end": 48 - } - }, - "sink": { - "start": 6, - "end": 12, - "column": { - "start": 1, - "end": 3 - }, - "content": "analytics.page({\\n userId: customer.id,\\n category: \\"Shopping Cart\\",\\n properties: {\\n path: \\"/cart/\\"+customer.bank_account_number\\n },\\n})" - }, - "parent_line_number": 6, - "snippet": "analytics.page({\\n userId: customer.id,\\n category: \\"Shopping Cart\\",\\n properties: {\\n path: \\"/cart/\\"+customer.bank_account_number\\n },\\n})", - "fingerprint": "df462286e9e34d817b61a361c26e8720_0", - "old_fingerprint": "95be5742a2ea59fc50223aba570b3b1f_0", - "code_extract": "analytics.page({\\n userId: customer.id,\\n category: \\"Shopping Cart\\",\\n properties: {\\n path: \\"/cart/\\"+customer.bank_account_number\\n },\\n});" - } - ] -}" -`; - -exports[`javascript_third_parties_segment datatype_in_track 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_segment", - "title": "Leakage of sensitive data to Segment", - "description": "## Description\\nLeaking sensitive data to third-party analytics tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Segment.\\n\\n## Remediations\\n\\nWhen sending data to analytics libraries, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Segment Node.js docs](https://segment.com/docs/connections/sources/catalog/libraries/server/node/)\\n- [Segment JavaScript docs](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_segment", - "line_number": 5, - "full_filename": "/tmp/bearer-scan/datatype_in_track.js", - "filename": ".", - "data_type": { - "category_uuid": "b5a3b0fd-dd5c-420d-91ce-dd2dddc8cc38", - "name": "IP address" - }, - "category_groups": [ - "Personal Data" - ], - "source": { - "start": 8, - "end": 8, - "column": { - "start": 15, - "end": 30 - } - }, - "sink": { - "start": 5, - "end": 9, - "column": { - "start": 1, - "end": 3 - }, - "content": "client.track({\\n event: \\"some event name\\",\\n userId: user.id,\\n userIpAddr: user.ip_address,\\n})" - }, - "parent_line_number": 5, - "snippet": "client.track({\\n event: \\"some event name\\",\\n userId: user.id,\\n userIpAddr: user.ip_address,\\n})", - "fingerprint": "df462286e9e34d817b61a361c26e8720_0", - "old_fingerprint": "7e3a0a37a21c50a3052b1d15f7ab8216_0", - "code_extract": "client.track({\\n event: \\"some event name\\",\\n userId: user.id,\\n userIpAddr: user.ip_address,\\n});" - }, - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_segment", - "title": "Leakage of sensitive data to Segment", - "description": "## Description\\nLeaking sensitive data to third-party analytics tools is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Segment.\\n\\n## Remediations\\n\\nWhen sending data to analytics libraries, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Segment Node.js docs](https://segment.com/docs/connections/sources/catalog/libraries/server/node/)\\n- [Segment JavaScript docs](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_segment", - "line_number": 17, - "full_filename": "/tmp/bearer-scan/datatype_in_track.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 17, - "end": 17, - "column": { - "start": 17, - "end": 27 - } - }, - "sink": { - "start": 17, - "end": 17, - "column": { - "start": 3, - "end": 28 - }, - "content": "browser.track(user.email)" - }, - "parent_line_number": 17, - "snippet": "browser.track(user.email)", - "fingerprint": "df462286e9e34d817b61a361c26e8720_1", - "old_fingerprint": "7e3a0a37a21c50a3052b1d15f7ab8216_1", - "code_extract": " browser.track(user.email)" - } - ] -}" -`; - -exports[`javascript_third_parties_segment ok_ignored_datatypes 1`] = `"{}"`; - -exports[`javascript_third_parties_segment ok_no_datatypes 1`] = `"{}"`; diff --git a/tests/javascript/third_parties/segment/test.js b/tests/javascript/third_parties/segment/test.js index 8ea691b9a..98eb97fb7 100644 --- a/tests/javascript/third_parties/segment/test.js +++ b/tests/javascript/third_parties/segment/test.js @@ -1,49 +1,80 @@ -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("datatype_in_alias", () => { + const testCase = "datatype_in_alias.js" + + const results = invoke(testCase) - test("datatype_in_alias", () => { - const testCase = "datatype_in_alias.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_group", () => { - const testCase = "datatype_in_group.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_group", () => { + const testCase = "datatype_in_group.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_identify", () => { - const testCase = "datatype_in_identify.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_identify", () => { + const testCase = "datatype_in_identify.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_page", () => { - const testCase = "datatype_in_page.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_page", () => { + const testCase = "datatype_in_page.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("datatype_in_track", () => { - const testCase = "datatype_in_track.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("datatype_in_track", () => { + const testCase = "datatype_in_track.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_ignored_datatypes", () => { - const testCase = "ok_ignored_datatypes.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_ignored_datatypes", () => { + const testCase = "ok_ignored_datatypes.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("ok_no_datatypes", () => { - const testCase = "ok_no_datatypes.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("ok_no_datatypes", () => { + const testCase = "ok_no_datatypes.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/segment/testdata/datatype_in_alias.js b/tests/javascript/third_parties/segment/testdata/datatype_in_alias.js index e3007f699..97fe7b873 100644 --- a/tests/javascript/third_parties/segment/testdata/datatype_in_alias.js +++ b/tests/javascript/third_parties/segment/testdata/datatype_in_alias.js @@ -4,6 +4,7 @@ const prodAnalytics = new Analytics({ writeKey: "product-write-key" }); const appAnalytics = new Analytics({ writeKey: "application-write-key" }); var user = getCurrentUser(); +// bearer:expected javascript_third_parties_segment appAnalytics.alias({ previousId: user.email, userId: user.id, diff --git a/tests/javascript/third_parties/segment/testdata/datatype_in_group.js b/tests/javascript/third_parties/segment/testdata/datatype_in_group.js index a0b3491db..76336a085 100644 --- a/tests/javascript/third_parties/segment/testdata/datatype_in_group.js +++ b/tests/javascript/third_parties/segment/testdata/datatype_in_group.js @@ -3,6 +3,7 @@ import { Analytics } from '@segment/analytics-node' const analytics = new Analytics({ writeKey: 'my-write-key' }); var user = getCurrentUser(); +// bearer:expected javascript_third_parties_segment analytics.group({ userId: user.id, groupId: user.job_title, diff --git a/tests/javascript/third_parties/segment/testdata/datatype_in_identify.js b/tests/javascript/third_parties/segment/testdata/datatype_in_identify.js index 910a87ef6..dc15269a6 100644 --- a/tests/javascript/third_parties/segment/testdata/datatype_in_identify.js +++ b/tests/javascript/third_parties/segment/testdata/datatype_in_identify.js @@ -2,6 +2,7 @@ const { Analytics } = require('@segment/analytics-node') const analytics = new Analytics({ write_key: 'some-write-key' }); var user = getCurrentUser(); +// bearer:expected javascript_third_parties_segment analytics.identify({ userId: user.id, traits: { @@ -15,4 +16,5 @@ analytics.identify({ import { AnalyticsBrowser } from '@segment/analytics-next' const browser = AnalyticsBrowser.load({ writeKey: 'write-key' }) +// bearer:expected javascript_third_parties_segment browser.identify(user.email) \ No newline at end of file diff --git a/tests/javascript/third_parties/segment/testdata/datatype_in_page.js b/tests/javascript/third_parties/segment/testdata/datatype_in_page.js index c7855160f..5a1017912 100644 --- a/tests/javascript/third_parties/segment/testdata/datatype_in_page.js +++ b/tests/javascript/third_parties/segment/testdata/datatype_in_page.js @@ -3,6 +3,7 @@ import { Analytics } from '@segment/analytics-node' const analytics = new Analytics({ writeKey: 'my-write-key' }); var customer = getCurrentUser(); +// bearer:expected javascript_third_parties_segment analytics.page({ userId: customer.id, category: "Shopping Cart", diff --git a/tests/javascript/third_parties/segment/testdata/datatype_in_track.js b/tests/javascript/third_parties/segment/testdata/datatype_in_track.js index f99ba55e2..d32a31da9 100644 --- a/tests/javascript/third_parties/segment/testdata/datatype_in_track.js +++ b/tests/javascript/third_parties/segment/testdata/datatype_in_track.js @@ -2,6 +2,7 @@ import { Analytics } from '@segment/analytics-node' const client = new Analytics({ write_key: 'some-write-key' }); +// bearer:expected javascript_third_parties_segment client.track({ event: "some event name", userId: user.id, @@ -14,5 +15,6 @@ import { AnalyticsBrowser } from "@segment/analytics-next" const browser = AnalyticsBrowser.load({ writeKey: 'write-key' }) document.body?.addEventListener('click', () => { +// bearer:expected javascript_third_parties_segment browser.track(user.email) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/sentry/__snapshots__/test.js.snap b/tests/javascript/third_parties/sentry/__snapshots__/test.js.snap deleted file mode 100644 index 614b424c5..000000000 --- a/tests/javascript/third_parties/sentry/__snapshots__/test.js.snap +++ /dev/null @@ -1,344 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`javascript_third_parties_sentry javascript_add_breadcrumb 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_sentry", - "title": "Leakage of sensitive data to Sentry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Sentry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Sentry Docs](https://docs.sentry.io/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_sentry", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/javascript_add_breadcrumb.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 2, - "end": 2, - "column": { - "start": 30, - "end": 40 - } - }, - "sink": { - "start": 1, - "end": 4, - "column": { - "start": 1, - "end": 3 - }, - "content": "Sentry.addBreadcrumb({\\n message: \`my message for \${user.email}\`,\\n // ...\\n})" - }, - "parent_line_number": 1, - "snippet": "Sentry.addBreadcrumb({\\n message: \`my message for \${user.email}\`,\\n // ...\\n})", - "fingerprint": "af49328f7c7aa692f05a50dc6ccda334_0", - "old_fingerprint": "d7d709503374e3bf595da3e08eeceec4_0", - "code_extract": "Sentry.addBreadcrumb({\\n message: \`my message for \${user.email}\`,\\n // ...\\n})" - } - ] -}" -`; - -exports[`javascript_third_parties_sentry javascript_capture_event 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_sentry", - "title": "Leakage of sensitive data to Sentry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Sentry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Sentry Docs](https://docs.sentry.io/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_sentry", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/javascript_capture_event.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 2, - "end": 2, - "column": { - "start": 45, - "end": 63 - } - }, - "sink": { - "start": 1, - "end": 6, - "column": { - "start": 1, - "end": 3 - }, - "content": "Sentry.captureEvent({\\n message: \\"user successfully logged in \\" + current_user.email,\\n stacktrace: [\\n // ...\\n ],\\n})" - }, - "parent_line_number": 1, - "snippet": "Sentry.captureEvent({\\n message: \\"user successfully logged in \\" + current_user.email,\\n stacktrace: [\\n // ...\\n ],\\n})", - "fingerprint": "af49328f7c7aa692f05a50dc6ccda334_0", - "old_fingerprint": "9255d3182ae19e404031e6003bf5aab4_0", - "code_extract": "Sentry.captureEvent({\\n message: \\"user successfully logged in \\" + current_user.email,\\n stacktrace: [\\n // ...\\n ],\\n})" - } - ] -}" -`; - -exports[`javascript_third_parties_sentry javascript_capture_exception 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_sentry", - "title": "Leakage of sensitive data to Sentry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Sentry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Sentry Docs](https://docs.sentry.io/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_sentry", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/javascript_capture_exception.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 2, - "end": 2, - "column": { - "start": 21, - "end": 39 - } - }, - "sink": { - "start": 1, - "end": 3, - "column": { - "start": 1, - "end": 2 - }, - "content": "Sentry.captureException(\\n new Error(\`user \${current_user.email} couldn't log in!\`)\\n)" - }, - "parent_line_number": 1, - "snippet": "Sentry.captureException(\\n new Error(\`user \${current_user.email} couldn't log in!\`)\\n)", - "fingerprint": "af49328f7c7aa692f05a50dc6ccda334_0", - "old_fingerprint": "0c0f755f6e40eb8e1d15b1b1b1441d37_0", - "code_extract": "Sentry.captureException(\\n new Error(\`user \${current_user.email} couldn't log in!\`)\\n)" - } - ] -}" -`; - -exports[`javascript_third_parties_sentry javascript_capture_message 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_sentry", - "title": "Leakage of sensitive data to Sentry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Sentry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Sentry Docs](https://docs.sentry.io/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_sentry", - "line_number": 1, - "full_filename": "/tmp/bearer-scan/javascript_capture_message.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 1, - "end": 1, - "column": { - "start": 60, - "end": 78 - } - }, - "sink": { - "start": 1, - "end": 1, - "column": { - "start": 1, - "end": 79 - }, - "content": "Sentry.captureMessage(\\"User has successfully signed in \\" + current_user.email)" - }, - "parent_line_number": 1, - "snippet": "Sentry.captureMessage(\\"User has successfully signed in \\" + current_user.email)", - "fingerprint": "af49328f7c7aa692f05a50dc6ccda334_0", - "old_fingerprint": "c0d18affe729b0be031a2c99547bb92d_0", - "code_extract": "Sentry.captureMessage(\\"User has successfully signed in \\" + current_user.email)" - } - ] -}" -`; - -exports[`javascript_third_parties_sentry javascript_configure_scope_set_extra 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_sentry", - "title": "Leakage of sensitive data to Sentry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Sentry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Sentry Docs](https://docs.sentry.io/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_sentry", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/javascript_configure_scope_set_extra.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 2, - "end": 2, - "column": { - "start": 26, - "end": 36 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 2, - "end": 37 - }, - "content": "scope.setExtra(\\"email\\", user.email)" - }, - "parent_line_number": 2, - "snippet": "scope.setExtra(\\"email\\", user.email)", - "fingerprint": "af49328f7c7aa692f05a50dc6ccda334_0", - "old_fingerprint": "7fa6f199e6bdbd6a051494d9ee166320_0", - "code_extract": "\\tscope.setExtra(\\"email\\", user.email);" - } - ] -}" -`; - -exports[`javascript_third_parties_sentry javascript_configure_scope_set_tag 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_sentry", - "title": "Leakage of sensitive data to Sentry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Sentry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Sentry Docs](https://docs.sentry.io/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_sentry", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/javascript_configure_scope_set_tag.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 2, - "end": 2, - "column": { - "start": 30, - "end": 40 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 3, - "end": 41 - }, - "content": "scope.setTag(\\"user_email\\", user.email)" - }, - "parent_line_number": 2, - "snippet": "scope.setTag(\\"user_email\\", user.email)", - "fingerprint": "af49328f7c7aa692f05a50dc6ccda334_0", - "old_fingerprint": "f3c682baa6ac5bd21f56c4f06348fe75_0", - "code_extract": " scope.setTag(\\"user_email\\", user.email)" - } - ] -}" -`; - -exports[`javascript_third_parties_sentry javascript_configure_scope_set_user 1`] = ` -"{ - "critical": [ - { - "cwe_ids": [ - "201" - ], - "id": "javascript_third_parties_sentry", - "title": "Leakage of sensitive data to Sentry", - "description": "## Description\\nLeaking sensitive data to third-party loggers is a common cause of data leaks and can lead to data breaches. This rule looks for instances of sensitive data sent to Sentry.\\n\\n## Remediations\\n\\nWhen logging errors or events, ensure all sensitive data is removed.\\n\\n## Resources\\n- [Sentry Docs](https://docs.sentry.io/)\\n", - "documentation_url": "https://docs.bearer.com/reference/rules/javascript_third_parties_sentry", - "line_number": 2, - "full_filename": "/tmp/bearer-scan/javascript_configure_scope_set_user.js", - "filename": ".", - "data_type": { - "category_uuid": "cef587dd-76db-430b-9e18-7b031e1a193b", - "name": "Email Address" - }, - "category_groups": [ - "PII", - "Personal Data" - ], - "source": { - "start": 2, - "end": 2, - "column": { - "start": 26, - "end": 36 - } - }, - "sink": { - "start": 2, - "end": 2, - "column": { - "start": 3, - "end": 39 - }, - "content": "scope.setUser({ email: user.email })" - }, - "parent_line_number": 2, - "snippet": "scope.setUser({ email: user.email })", - "fingerprint": "af49328f7c7aa692f05a50dc6ccda334_0", - "old_fingerprint": "9a4f46bec10157052d7e2ca15329cd45_0", - "code_extract": " scope.setUser({ email: user.email })" - } - ] -}" -`; diff --git a/tests/javascript/third_parties/sentry/test.js b/tests/javascript/third_parties/sentry/test.js index 5395e1cc2..a008224d2 100644 --- a/tests/javascript/third_parties/sentry/test.js +++ b/tests/javascript/third_parties/sentry/test.js @@ -1,49 +1,80 @@ -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("javascript_add_breadcrumb", () => { + const testCase = "javascript_add_breadcrumb.js" + + const results = invoke(testCase) - test("javascript_add_breadcrumb", () => { - const testCase = "javascript_add_breadcrumb.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("javascript_capture_event", () => { - const testCase = "javascript_capture_event.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("javascript_capture_event", () => { + const testCase = "javascript_capture_event.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("javascript_capture_exception", () => { - const testCase = "javascript_capture_exception.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("javascript_capture_exception", () => { + const testCase = "javascript_capture_exception.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("javascript_capture_message", () => { - const testCase = "javascript_capture_message.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("javascript_capture_message", () => { + const testCase = "javascript_capture_message.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("javascript_configure_scope_set_extra", () => { - const testCase = "javascript_configure_scope_set_extra.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("javascript_configure_scope_set_extra", () => { + const testCase = "javascript_configure_scope_set_extra.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("javascript_configure_scope_set_tag", () => { - const testCase = "javascript_configure_scope_set_tag.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("javascript_configure_scope_set_tag", () => { + const testCase = "javascript_configure_scope_set_tag.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) - test("javascript_configure_scope_set_user", () => { - const testCase = "javascript_configure_scope_set_user.js" - expect(invoke(testCase)).toMatchSnapshot(); - }) + test("javascript_configure_scope_set_user", () => { + const testCase = "javascript_configure_scope_set_user.js" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) }) \ No newline at end of file diff --git a/tests/javascript/third_parties/sentry/testdata/javascript_add_breadcrumb.js b/tests/javascript/third_parties/sentry/testdata/javascript_add_breadcrumb.js index 66c649a75..d2106ba7e 100644 --- a/tests/javascript/third_parties/sentry/testdata/javascript_add_breadcrumb.js +++ b/tests/javascript/third_parties/sentry/testdata/javascript_add_breadcrumb.js @@ -1,3 +1,4 @@ +// bearer:expected javascript_third_parties_sentry Sentry.addBreadcrumb({ message: `my message for ${user.email}`, // ... diff --git a/tests/javascript/third_parties/sentry/testdata/javascript_capture_event.js b/tests/javascript/third_parties/sentry/testdata/javascript_capture_event.js index a45985fd9..2f6272bf3 100644 --- a/tests/javascript/third_parties/sentry/testdata/javascript_capture_event.js +++ b/tests/javascript/third_parties/sentry/testdata/javascript_capture_event.js @@ -1,3 +1,4 @@ +// bearer:expected javascript_third_parties_sentry Sentry.captureEvent({ message: "user successfully logged in " + current_user.email, stacktrace: [ diff --git a/tests/javascript/third_parties/sentry/testdata/javascript_capture_exception.js b/tests/javascript/third_parties/sentry/testdata/javascript_capture_exception.js index 127be912b..a8558b3c9 100644 --- a/tests/javascript/third_parties/sentry/testdata/javascript_capture_exception.js +++ b/tests/javascript/third_parties/sentry/testdata/javascript_capture_exception.js @@ -1,3 +1,4 @@ +// bearer:expected javascript_third_parties_sentry Sentry.captureException( new Error(`user ${current_user.email} couldn't log in!`) ) diff --git a/tests/javascript/third_parties/sentry/testdata/javascript_capture_message.js b/tests/javascript/third_parties/sentry/testdata/javascript_capture_message.js index 9196e8aff..3125671a5 100644 --- a/tests/javascript/third_parties/sentry/testdata/javascript_capture_message.js +++ b/tests/javascript/third_parties/sentry/testdata/javascript_capture_message.js @@ -1 +1,2 @@ +// bearer:expected javascript_third_parties_sentry Sentry.captureMessage("User has successfully signed in " + current_user.email) diff --git a/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_extra.js b/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_extra.js index 168e4586d..cbbb10df5 100644 --- a/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_extra.js +++ b/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_extra.js @@ -1,3 +1,4 @@ Sentry.configureScope((scope) => { +// bearer:expected javascript_third_parties_sentry scope.setExtra("email", user.email); }); diff --git a/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_tag.js b/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_tag.js index d782c6b22..d12c84d0c 100644 --- a/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_tag.js +++ b/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_tag.js @@ -1,3 +1,4 @@ Sentry.configureScope((scope) => { +// bearer:expected javascript_third_parties_sentry scope.setTag("user_email", user.email) }) diff --git a/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_user.js b/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_user.js index 12b1fdf78..a35961c9c 100644 --- a/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_user.js +++ b/tests/javascript/third_parties/sentry/testdata/javascript_configure_scope_set_user.js @@ -1,3 +1,4 @@ Sentry.configureScope((scope) => { +// bearer:expected javascript_third_parties_sentry scope.setUser({ email: user.email }) })