diff --git a/.github/workflows/code_scanning.yml b/.github/workflows/code_scanning.yml index 26584b84a..f7f42e705 100644 --- a/.github/workflows/code_scanning.yml +++ b/.github/workflows/code_scanning.yml @@ -8,9 +8,11 @@ on: branches: [ "main" ] schedule: - cron: '39 12 * * 2' - + workflow_dispatch: + env: LGTM_INDEX_XML_MODE: all + LGTM_INDEX_FILTERS: "include:**/*.json" jobs: analyze: @@ -35,6 +37,24 @@ jobs: mv $dir .github/codeql/extensions/$dir done + - name: Ensure presence of cds shell command + run: | + if ! command -v cds &> /dev/null + then + npm install -g @sap/cds-dk + fi + + # Compile .cds files to .cds.json files. + - name: Compile CAP CDS files + run: | + for cds_file in $(find . -type f \( -iname '*.cds' \) -print) + do + echo "I am compiling $cds_file" + cds compile $cds_file \ + -2 json \ + -o "$cds_file.json" + done + # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 @@ -46,17 +66,17 @@ jobs: - name: Perform CodeQL Analysis id: analyze uses: github/codeql-action/analyze@v3 - + - name: Setup Python uses: actions/setup-python@v5 with: - python-version: '3.10' - + python-version: '3.10' + - uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip - + - name: Validate results continue-on-error: true id: validate @@ -66,7 +86,7 @@ jobs: sarif diff ${{ steps.analyze.outputs.sarif-output }} .github/workflows/javascript.sarif.expected -o sarif-diff.json cat sarif-diff.json ! grep -q "[1-9]" sarif-diff.json - + - name: Upload sarif change if: steps.validate.outcome != 'success' uses: actions/upload-artifact@v4 @@ -75,10 +95,9 @@ jobs: path: | sarif-diff.json ${{ steps.analyze.outputs.sarif-output }} - + - name: Unexpected Code Scanning results if: steps.validate.outcome != 'success' run: | cat sarif-diff.json echo "::error::Unexpected Code Scanning results!" && exit 1 - diff --git a/.github/workflows/javascript.sarif.expected b/.github/workflows/javascript.sarif.expected index 37a9f3592..619cca50c 100644 --- a/.github/workflows/javascript.sarif.expected +++ b/.github/workflows/javascript.sarif.expected @@ -6,7 +6,7 @@ "driver" : { "name" : "CodeQL", "organization" : "GitHub", - "semanticVersion" : "2.16.3", + "semanticVersion" : "2.16.4", "notifications" : [ { "id" : "cli/expected-extracted-files/javascript", "name" : "cli/expected-extracted-files/javascript", @@ -43,36 +43,78 @@ "rules" : [ ] }, "extensions" : [ { - "name" : "advanced-security/javascript-sap-ui5-queries", - "semanticVersion" : "0.5.0+6519bc2c9f3d9be292ae8322aa3ea18c081bb38b", + "name" : "advanced-security/javascript-sap-cap-queries", + "semanticVersion" : "0.1.0+b1fbd510971da2b65671de1296cb2c3288f6b252", "rules" : [ { - "id" : "js/ui5-clickjacking", - "name" : "js/ui5-clickjacking", + "id" : "js/cap-sql-injection", + "name" : "js/cap-sql-injection", "shortDescription" : { - "text" : "UI5 Clickjacking" + "text" : "CQL query built from user-controlled sources" }, "fullDescription" : { - "text" : "The absence of frame options allows for clickjacking." + "text" : "Building a CQL query from user-controlled sources is vulnerable to insertion of malicious code by the user." }, "defaultConfiguration" : { "enabled" : true, "level" : "error" }, "help" : { - "text" : "# Clickjacking\n\nUI5 applications that do not explicitly set the frame options to `deny` may be vulnerable to UI redress attacks (”clickjacking”). In these attacks, the vulnerable site is loaded in a frame on an attacker-controlled site which uses opaque or transparent layers to trick the user into unintentionally clicking a button or link on the vulnerable site.\n\n## Recommendation\n\nExplicitly set the frame options to `\"deny\"`, either through `window[\"sap-ui-config\"]`, or `data-sap-ui-frameOptions` attribute of the script tag where it sources the bootstrap script `\"sap-ui-core.js\"`:\n\n``` javascript\nwindow[\"sap-ui-config\"] = {\n frameOptions: \"deny\",\n ...\n};\n```\n\n``` javascript\nwindow[\"sap-ui-config\"].frameOptions = \"deny\";\n```\n\n``` html\n\n```\n\n## Example\n\n### Setting the Frame Options to `\"allow\"`\n\nThis UI5 application explicitly allows to be embedded in other applications.\n\n```javascript\n\n\n \n ...\n \n\n \n \n ...\n\n```\n\n### Not Setting the Frame Options to Anything\n\nThe default value of `window[\"sap-ui-config\"]` and `data-sap-ui-frameOptions` are both `\"allow\"`, which makes leaving it untouched allows the application to be embedded.\n\n## References\n* OWASP: [Clickjacking Defense Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html).\n* Mozilla: [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options).\n* SAP UI5 Documentation: [Frame Options](https://sapui5.hana.ondemand.com/sdk/#/topic/62d9c4d8f5ad49aa914624af9551beb7.html).\n* SAP UI5 Documentation: [Allowlist Service](https://sapui5.hana.ondemand.com/sdk/#/topic/d04a6d41480c4396af16b5d2b25509ec.html).\n* Common Weakness Enumeration: [CWE-451](https://cwe.mitre.org/data/definitions/451.html).\n", - "markdown" : "# Clickjacking\n\nUI5 applications that do not explicitly set the frame options to `deny` may be vulnerable to UI redress attacks (”clickjacking”). In these attacks, the vulnerable site is loaded in a frame on an attacker-controlled site which uses opaque or transparent layers to trick the user into unintentionally clicking a button or link on the vulnerable site.\n\n## Recommendation\n\nExplicitly set the frame options to `\"deny\"`, either through `window[\"sap-ui-config\"]`, or `data-sap-ui-frameOptions` attribute of the script tag where it sources the bootstrap script `\"sap-ui-core.js\"`:\n\n``` javascript\nwindow[\"sap-ui-config\"] = {\n frameOptions: \"deny\",\n ...\n};\n```\n\n``` javascript\nwindow[\"sap-ui-config\"].frameOptions = \"deny\";\n```\n\n``` html\n\n```\n\n## Example\n\n### Setting the Frame Options to `\"allow\"`\n\nThis UI5 application explicitly allows to be embedded in other applications.\n\n```javascript\n\n\n \n ...\n \n\n \n \n ...\n\n```\n\n### Not Setting the Frame Options to Anything\n\nThe default value of `window[\"sap-ui-config\"]` and `data-sap-ui-frameOptions` are both `\"allow\"`, which makes leaving it untouched allows the application to be embedded.\n\n## References\n* OWASP: [Clickjacking Defense Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html).\n* Mozilla: [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options).\n* SAP UI5 Documentation: [Frame Options](https://sapui5.hana.ondemand.com/sdk/#/topic/62d9c4d8f5ad49aa914624af9551beb7.html).\n* SAP UI5 Documentation: [Allowlist Service](https://sapui5.hana.ondemand.com/sdk/#/topic/d04a6d41480c4396af16b5d2b25509ec.html).\n* Common Weakness Enumeration: [CWE-451](https://cwe.mitre.org/data/definitions/451.html).\n" + "text" : "# CQL query built from user-controlled sources\n\nIf a database query is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.\n\n## Recommendation\n\nCAP's intrinsic data querying engine is immune with regards to SQL injections that are introduced by query parameter values that are derived from malicious user input. CQL statements are transformed into prepared statements that are executed in SQL databases such as SAP HANA. \nInjections are still possible even via CQL when the query structure (e.g. target entity, columns etc.) is based on user input.\n\n## Examples\n\nThis CAP application uses user submitted input as entity and column in a CQL query without any validation.\n\n``` javascript\nconst entity = \nconst column = \nSELECT.from(entity).columns(column)\n```\n\n## References\n\n- OWASP: [Log Injection](https://owasp.org/www-community/attacks/Log_Injection).\n- OWASP: [Log Injection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html).\n- SAP CAPire Documentation: [Security Aspects](https://cap.cloud.sap/docs/guides/security/aspects#common-injection-attacks).\n", + "markdown" : "# CQL query built from user-controlled sources\n\nIf a database query is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.\n\n## Recommendation\n\nCAP's intrinsic data querying engine is immune with regards to SQL injections that are introduced by query parameter values that are derived from malicious user input. CQL statements are transformed into prepared statements that are executed in SQL databases such as SAP HANA. \nInjections are still possible even via CQL when the query structure (e.g. target entity, columns etc.) is based on user input.\n\n## Examples\n\nThis CAP application uses user submitted input as entity and column in a CQL query without any validation.\n\n``` javascript\nconst entity = \nconst column = \nSELECT.from(entity).columns(column)\n```\n\n## References\n\n- OWASP: [Log Injection](https://owasp.org/www-community/attacks/Log_Injection).\n- OWASP: [Log Injection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html).\n- SAP CAPire Documentation: [Security Aspects](https://cap.cloud.sap/docs/guides/security/aspects#common-injection-attacks).\n" }, "properties" : { - "tags" : [ "security", "external/cwe/cwe-451" ], - "description" : "The absence of frame options allows for clickjacking.", - "id" : "js/ui5-clickjacking", - "kind" : "problem", - "name" : "UI5 Clickjacking", + "tags" : [ "security" ], + "description" : "Building a CQL query from user-controlled sources is vulnerable to insertion of\n malicious code by the user.", + "id" : "js/cap-sql-injection", + "kind" : "path-problem", + "name" : "CQL query built from user-controlled sources", + "precision" : "high", + "problem.severity" : "error", + "security-severity" : "8.8" + } + }, { + "id" : "js/cap-log-injection", + "name" : "js/cap-log-injection", + "shortDescription" : { + "text" : "CAP Log injection" + }, + "fullDescription" : { + "text" : "Building log entries from user-controlled sources is vulnerable to insertion of forged log entries by a malicious user." + }, + "defaultConfiguration" : { + "enabled" : true, + "level" : "error" + }, + "help" : { + "text" : "# CAP Log Injection\n\nIf unsanitized user input is written to a log entry using the CAP Node.js logging API, a malicious user may be able to forge new log entries.\n\nCAP Node.js offers a CLRF-safe logging API that should be used for application log entries that are logged as plaintext. If the entry is interpreted as HTML, then arbitrary HTML code my be included to forge log entries.\n\n## Recommendation\n\nCAP applications need to care for escaping user data that is used as input parameter for application logging. It's recommended to make use of an existing Encoder such as OWASP ESAPI.\n\n## Examples\n\nThis CAP service directly logs what the user submitted via the `req` request.\n\n``` javascript\nimport cds from '@sap/cds'\nconst { Books } = cds.entities ('sap.capire.bookshop')\n\nclass SampleVulnService extends cds.ApplicationService { init(){\n this.on ('submitOrder', async req => {\n const {book,quantity} = req.data\n const LOG = cds.log(\"nodejs\");\n LOG.info(\"test\" + book); // Log injection alert\n })\n\n return super.init()\n}}\n```\n\n## References\n\n- OWASP: [Log Injection](https://owasp.org/www-community/attacks/Log_Injection).\n- OWASP: [Log Injection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html).\n- SAP CAPire Documentation: [Security Aspects](https://cap.cloud.sap/docs/guides/security/aspects#common-injection-attacks).\n", + "markdown" : "# CAP Log Injection\n\nIf unsanitized user input is written to a log entry using the CAP Node.js logging API, a malicious user may be able to forge new log entries.\n\nCAP Node.js offers a CLRF-safe logging API that should be used for application log entries that are logged as plaintext. If the entry is interpreted as HTML, then arbitrary HTML code my be included to forge log entries.\n\n## Recommendation\n\nCAP applications need to care for escaping user data that is used as input parameter for application logging. It's recommended to make use of an existing Encoder such as OWASP ESAPI.\n\n## Examples\n\nThis CAP service directly logs what the user submitted via the `req` request.\n\n``` javascript\nimport cds from '@sap/cds'\nconst { Books } = cds.entities ('sap.capire.bookshop')\n\nclass SampleVulnService extends cds.ApplicationService { init(){\n this.on ('submitOrder', async req => {\n const {book,quantity} = req.data\n const LOG = cds.log(\"nodejs\");\n LOG.info(\"test\" + book); // Log injection alert\n })\n\n return super.init()\n}}\n```\n\n## References\n\n- OWASP: [Log Injection](https://owasp.org/www-community/attacks/Log_Injection).\n- OWASP: [Log Injection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html).\n- SAP CAPire Documentation: [Security Aspects](https://cap.cloud.sap/docs/guides/security/aspects#common-injection-attacks).\n" + }, + "properties" : { + "tags" : [ "security" ], + "description" : "Building log entries from user-controlled sources is vulnerable to\n insertion of forged log entries by a malicious user.", + "id" : "js/cap-log-injection", + "kind" : "path-problem", + "name" : "CAP Log injection", "precision" : "medium", "problem.severity" : "error", "security-severity" : "6.1" } + } ], + "locations" : [ { + "uri" : "file:///home/runner/work/codeql-sap-js/codeql-sap-js/javascript/frameworks/cap/src/", + "description" : { + "text" : "The QL pack root directory." + } }, { + "uri" : "file:///home/runner/work/codeql-sap-js/codeql-sap-js/javascript/frameworks/cap/src/qlpack.yml", + "description" : { + "text" : "The QL pack definition file." + } + } ] + }, { + "name" : "advanced-security/javascript-sap-ui5-queries", + "semanticVersion" : "0.5.0+b1fbd510971da2b65671de1296cb2c3288f6b252", + "rules" : [ { "id" : "js/ui5-xss", "name" : "js/ui5-xss", "shortDescription" : { @@ -180,90 +222,65 @@ "problem.severity" : "error", "security-severity" : "7.8" } - } ], - "locations" : [ { - "uri" : "file:///home/runner/work/codeql-sap-js/codeql-sap-js/javascript/frameworks/ui5/src/", - "description" : { - "text" : "The QL pack root directory." - } - }, { - "uri" : "file:///home/runner/work/codeql-sap-js/codeql-sap-js/javascript/frameworks/ui5/src/qlpack.yml", - "description" : { - "text" : "The QL pack definition file." - } - } ] - }, { - "name" : "advanced-security/javascript-sap-cap-queries", - "semanticVersion" : "0.1.0+6519bc2c9f3d9be292ae8322aa3ea18c081bb38b", - "rules" : [ { - "id" : "js/cap-sql-injection", - "name" : "js/cap-sql-injection", - "shortDescription" : { - "text" : "CQL query built from user-controlled sources" - }, - "fullDescription" : { - "text" : "Building a CQL query from user-controlled sources is vulnerable to insertion of malicious code by the user." - }, - "defaultConfiguration" : { - "enabled" : true, - "level" : "error" - }, - "help" : { - "text" : "# SQL Injection\n\nIf a database query is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.\n\n## Recommendation\n\nCAP's intrinsic data querying engine is immune with regards to SQL injections that are introduced by query parameter values that are derived from malicious user input. CQL statements are transformed into prepared statements that are executed in SQL databases such as SAP HANA. \nInjections are still possible even via CQL when the query structure (e.g. target entity, columns etc.) is based on user input.\n\n## Examples\n\nThis CAP application uses user submitted input as entity and column in a CQL query without any validation.\n\n``` javascript\nconst entity = \nconst column = \nSELECT.from(entity).columns(column)\n```\n\n## References\n\n- OWASP: [Log Injection](https://owasp.org/www-community/attacks/Log_Injection).\n- OWASP: [Log Injection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html).\n- SAP CAPire Documentation: [Security Aspects](https://cap.cloud.sap/docs/guides/security/aspects#common-injection-attacks).\n", - "markdown" : "# SQL Injection\n\nIf a database query is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.\n\n## Recommendation\n\nCAP's intrinsic data querying engine is immune with regards to SQL injections that are introduced by query parameter values that are derived from malicious user input. CQL statements are transformed into prepared statements that are executed in SQL databases such as SAP HANA. \nInjections are still possible even via CQL when the query structure (e.g. target entity, columns etc.) is based on user input.\n\n## Examples\n\nThis CAP application uses user submitted input as entity and column in a CQL query without any validation.\n\n``` javascript\nconst entity = \nconst column = \nSELECT.from(entity).columns(column)\n```\n\n## References\n\n- OWASP: [Log Injection](https://owasp.org/www-community/attacks/Log_Injection).\n- OWASP: [Log Injection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html).\n- SAP CAPire Documentation: [Security Aspects](https://cap.cloud.sap/docs/guides/security/aspects#common-injection-attacks).\n" - }, - "properties" : { - "tags" : [ "security" ], - "description" : "Building a CQL query from user-controlled sources is vulnerable to insertion of\n malicious code by the user.", - "id" : "js/cap-sql-injection", - "kind" : "path-problem", - "name" : "CQL query built from user-controlled sources", - "precision" : "high", - "problem.severity" : "error", - "security-severity" : "8.8" - } }, { - "id" : "js/cap-log-injection", - "name" : "js/cap-log-injection", + "id" : "js/ui5-clickjacking", + "name" : "js/ui5-clickjacking", "shortDescription" : { - "text" : "CAP Log injection" + "text" : "UI5 Clickjacking" }, "fullDescription" : { - "text" : "Building log entries from user-controlled sources is vulnerable to insertion of forged log entries by a malicious user." + "text" : "The absence of frame options allows for clickjacking." }, "defaultConfiguration" : { "enabled" : true, "level" : "error" }, "help" : { - "text" : "# Log Injection\n\nIf unsanitized user input is written to a log entry using the CAP Node.js logging API, a malicious user may be able to forge new log entries.\n\nCAP Node.js offers a CLRF-safe logging API that should be used for application log entries that are logged as plaintext. If the entry is interpreted as HTML, then arbitrary HTML code my be included to forge log entries.\n\n## Recommendation\n\nCAP applications need to care for escaping user data that is used as input parameter for application logging. It's recommended to make use of an existing Encoder such as OWASP ESAPI.\n\n## Examples\n\nThis CAP service directly logs what the user submitted via the `req` request.\n\n``` javascript\nimport cds from '@sap/cds'\nconst { Books } = cds.entities ('sap.capire.bookshop')\n\nclass SampleVulnService extends cds.ApplicationService { init(){\n this.on ('submitOrder', async req => {\n const {book,quantity} = req.data\n const LOG = cds.log(\"nodejs\");\n LOG.info(\"test\" + book); // Log injection alert\n })\n\n return super.init()\n}}\n```\n\n## References\n\n- OWASP: [Log Injection](https://owasp.org/www-community/attacks/Log_Injection).\n- OWASP: [Log Injection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html).\n- SAP CAPire Documentation: [Security Aspects](https://cap.cloud.sap/docs/guides/security/aspects#common-injection-attacks).\n", - "markdown" : "# Log Injection\n\nIf unsanitized user input is written to a log entry using the CAP Node.js logging API, a malicious user may be able to forge new log entries.\n\nCAP Node.js offers a CLRF-safe logging API that should be used for application log entries that are logged as plaintext. If the entry is interpreted as HTML, then arbitrary HTML code my be included to forge log entries.\n\n## Recommendation\n\nCAP applications need to care for escaping user data that is used as input parameter for application logging. It's recommended to make use of an existing Encoder such as OWASP ESAPI.\n\n## Examples\n\nThis CAP service directly logs what the user submitted via the `req` request.\n\n``` javascript\nimport cds from '@sap/cds'\nconst { Books } = cds.entities ('sap.capire.bookshop')\n\nclass SampleVulnService extends cds.ApplicationService { init(){\n this.on ('submitOrder', async req => {\n const {book,quantity} = req.data\n const LOG = cds.log(\"nodejs\");\n LOG.info(\"test\" + book); // Log injection alert\n })\n\n return super.init()\n}}\n```\n\n## References\n\n- OWASP: [Log Injection](https://owasp.org/www-community/attacks/Log_Injection).\n- OWASP: [Log Injection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html).\n- SAP CAPire Documentation: [Security Aspects](https://cap.cloud.sap/docs/guides/security/aspects#common-injection-attacks).\n" + "text" : "# Clickjacking\n\nUI5 applications that do not explicitly set the frame options to `deny` may be vulnerable to UI redress attacks (”clickjacking”). In these attacks, the vulnerable site is loaded in a frame on an attacker-controlled site which uses opaque or transparent layers to trick the user into unintentionally clicking a button or link on the vulnerable site.\n\n## Recommendation\n\nExplicitly set the frame options to `\"deny\"`, either through `window[\"sap-ui-config\"]`, or `data-sap-ui-frameOptions` attribute of the script tag where it sources the bootstrap script `\"sap-ui-core.js\"`:\n\n``` javascript\nwindow[\"sap-ui-config\"] = {\n frameOptions: \"deny\",\n ...\n};\n```\n\n``` javascript\nwindow[\"sap-ui-config\"].frameOptions = \"deny\";\n```\n\n``` html\n\n```\n\n## Example\n\n### Setting the Frame Options to `\"allow\"`\n\nThis UI5 application explicitly allows to be embedded in other applications.\n\n```javascript\n\n\n \n ...\n \n\n \n \n ...\n\n```\n\n### Not Setting the Frame Options to Anything\n\nThe default value of `window[\"sap-ui-config\"]` and `data-sap-ui-frameOptions` are both `\"allow\"`, which makes leaving it untouched allows the application to be embedded.\n\n## References\n* OWASP: [Clickjacking Defense Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html).\n* Mozilla: [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options).\n* SAP UI5 Documentation: [Frame Options](https://sapui5.hana.ondemand.com/sdk/#/topic/62d9c4d8f5ad49aa914624af9551beb7.html).\n* SAP UI5 Documentation: [Allowlist Service](https://sapui5.hana.ondemand.com/sdk/#/topic/d04a6d41480c4396af16b5d2b25509ec.html).\n* Common Weakness Enumeration: [CWE-451](https://cwe.mitre.org/data/definitions/451.html).\n", + "markdown" : "# Clickjacking\n\nUI5 applications that do not explicitly set the frame options to `deny` may be vulnerable to UI redress attacks (”clickjacking”). In these attacks, the vulnerable site is loaded in a frame on an attacker-controlled site which uses opaque or transparent layers to trick the user into unintentionally clicking a button or link on the vulnerable site.\n\n## Recommendation\n\nExplicitly set the frame options to `\"deny\"`, either through `window[\"sap-ui-config\"]`, or `data-sap-ui-frameOptions` attribute of the script tag where it sources the bootstrap script `\"sap-ui-core.js\"`:\n\n``` javascript\nwindow[\"sap-ui-config\"] = {\n frameOptions: \"deny\",\n ...\n};\n```\n\n``` javascript\nwindow[\"sap-ui-config\"].frameOptions = \"deny\";\n```\n\n``` html\n\n```\n\n## Example\n\n### Setting the Frame Options to `\"allow\"`\n\nThis UI5 application explicitly allows to be embedded in other applications.\n\n```javascript\n\n\n \n ...\n \n\n \n \n ...\n\n```\n\n### Not Setting the Frame Options to Anything\n\nThe default value of `window[\"sap-ui-config\"]` and `data-sap-ui-frameOptions` are both `\"allow\"`, which makes leaving it untouched allows the application to be embedded.\n\n## References\n* OWASP: [Clickjacking Defense Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html).\n* Mozilla: [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options).\n* SAP UI5 Documentation: [Frame Options](https://sapui5.hana.ondemand.com/sdk/#/topic/62d9c4d8f5ad49aa914624af9551beb7.html).\n* SAP UI5 Documentation: [Allowlist Service](https://sapui5.hana.ondemand.com/sdk/#/topic/d04a6d41480c4396af16b5d2b25509ec.html).\n* Common Weakness Enumeration: [CWE-451](https://cwe.mitre.org/data/definitions/451.html).\n" }, "properties" : { - "tags" : [ "security" ], - "description" : "Building log entries from user-controlled sources is vulnerable to\n insertion of forged log entries by a malicious user.", - "id" : "js/cap-log-injection", - "kind" : "path-problem", - "name" : "CAP Log injection", + "tags" : [ "security", "external/cwe/cwe-451" ], + "description" : "The absence of frame options allows for clickjacking.", + "id" : "js/ui5-clickjacking", + "kind" : "problem", + "name" : "UI5 Clickjacking", "precision" : "medium", "problem.severity" : "error", "security-severity" : "6.1" } } ], "locations" : [ { - "uri" : "file:///home/runner/work/codeql-sap-js/codeql-sap-js/javascript/frameworks/cap/src/", + "uri" : "file:///home/runner/work/codeql-sap-js/codeql-sap-js/javascript/frameworks/ui5/src/", "description" : { "text" : "The QL pack root directory." } }, { - "uri" : "file:///home/runner/work/codeql-sap-js/codeql-sap-js/javascript/frameworks/cap/src/qlpack.yml", + "uri" : "file:///home/runner/work/codeql-sap-js/codeql-sap-js/javascript/frameworks/ui5/src/qlpack.yml", "description" : { "text" : "The QL pack definition file." } } ] + }, { + "name" : "generated/extension-pack", + "semanticVersion" : "0.0.0", + "locations" : [ { + "uri" : "file:///home/runner/work/_temp/codeql_databases/javascript/temp/extension-pack/", + "description" : { + "text" : "The QL pack root directory." + } + }, { + "uri" : "file:///home/runner/work/_temp/codeql_databases/javascript/temp/extension-pack/codeql-pack.yml", + "description" : { + "text" : "The QL pack definition file." + } + } ], + "properties" : { + "isCodeQLModelPack" : true + } }, { "name" : "codeql/javascript-queries", - "semanticVersion" : "0.8.9+8a00a45b32679ddced400ab256706c79c1169e38", + "semanticVersion" : "0.8.10+2daf50500ca8f7eb914c82e88dec36652bfbe8fd", "notifications" : [ { "id" : "js/diagnostics/extraction-errors", "name" : "js/diagnostics/extraction-errors", @@ -303,1020 +320,966 @@ } } ], "rules" : [ { - "id" : "js/disabling-electron-websecurity", - "name" : "js/disabling-electron-websecurity", + "id" : "js/unsafe-external-link", + "name" : "js/unsafe-external-link", "shortDescription" : { - "text" : "Disabling Electron webSecurity" + "text" : "Potentially unsafe external link" }, "fullDescription" : { - "text" : "Disabling webSecurity can cause critical security vulnerabilities." + "text" : "External links that open in a new tab or window but do not specify link type 'noopener' or 'noreferrer' are a potential security risk." }, "defaultConfiguration" : { "enabled" : true, - "level" : "error" + "level" : "warning" }, "help" : { - "text" : "# Disabling Electron webSecurity\nElectron is secure by default through a same-origin policy requiring all JavaScript and CSS code to originate from the machine running the Electron application. Setting the `webSecurity` property of a `webPreferences` object to `false` will disable the same-origin policy.\n\nDisabling the same-origin policy is strongly discouraged.\n\n\n## Recommendation\nDo not disable `webSecurity`.\n\n\n## Example\nThe following example shows `webSecurity` being disabled.\n\n\n```javascript\nconst mainWindow = new BrowserWindow({\n webPreferences: {\n webSecurity: false\n }\n})\n```\nThis is problematic, since it allows the execution of insecure code from other domains.\n\n\n## References\n* Electron Documentation: [Security, Native Capabilities, and Your Responsibility](https://electronjs.org/docs/tutorial/security#5-do-not-disable-websecurity)\n* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html).\n", - "markdown" : "# Disabling Electron webSecurity\nElectron is secure by default through a same-origin policy requiring all JavaScript and CSS code to originate from the machine running the Electron application. Setting the `webSecurity` property of a `webPreferences` object to `false` will disable the same-origin policy.\n\nDisabling the same-origin policy is strongly discouraged.\n\n\n## Recommendation\nDo not disable `webSecurity`.\n\n\n## Example\nThe following example shows `webSecurity` being disabled.\n\n\n```javascript\nconst mainWindow = new BrowserWindow({\n webPreferences: {\n webSecurity: false\n }\n})\n```\nThis is problematic, since it allows the execution of insecure code from other domains.\n\n\n## References\n* Electron Documentation: [Security, Native Capabilities, and Your Responsibility](https://electronjs.org/docs/tutorial/security#5-do-not-disable-websecurity)\n* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html).\n" + "text" : "# Potentially unsafe external link\nHTML links that open in a new tab or window allow the target page to access the DOM of the origin page using `window.opener` unless link type `noopener` or `noreferrer` is specified. This is a potential security risk.\n\n\n## Recommendation\nSpecify the link type by adding an attribute `rel=\"noopener noreferrer\"`.\n\n\n## Example\nIn the following example, a JSX element is created that corresponds to an HTML link opening the URL `http://example.com` in a new tab. Since it does not specify a link type, that page will be able to access the DOM of the origin page.\n\n\n```javascript\nvar link = Example;\n\n```\nTo fix this vulnerability, add a `rel` attribute:\n\n\n```javascript\nvar link = Example;\n\n```\n\n## References\n* Mathias Bynens: [About rel=noopener](https://mathiasbynens.github.io/rel-noopener/).\n* Mozilla Developer Network: [HTML Anchor Element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a).\n* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html).\n* Common Weakness Enumeration: [CWE-1022](https://cwe.mitre.org/data/definitions/1022.html).\n", + "markdown" : "# Potentially unsafe external link\nHTML links that open in a new tab or window allow the target page to access the DOM of the origin page using `window.opener` unless link type `noopener` or `noreferrer` is specified. This is a potential security risk.\n\n\n## Recommendation\nSpecify the link type by adding an attribute `rel=\"noopener noreferrer\"`.\n\n\n## Example\nIn the following example, a JSX element is created that corresponds to an HTML link opening the URL `http://example.com` in a new tab. Since it does not specify a link type, that page will be able to access the DOM of the origin page.\n\n\n```javascript\nvar link = Example;\n\n```\nTo fix this vulnerability, add a `rel` attribute:\n\n\n```javascript\nvar link = Example;\n\n```\n\n## References\n* Mathias Bynens: [About rel=noopener](https://mathiasbynens.github.io/rel-noopener/).\n* Mozilla Developer Network: [HTML Anchor Element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a).\n* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html).\n* Common Weakness Enumeration: [CWE-1022](https://cwe.mitre.org/data/definitions/1022.html).\n" }, "properties" : { - "tags" : [ "security", "frameworks/electron", "external/cwe/cwe-79" ], - "description" : "Disabling webSecurity can cause critical security vulnerabilities.", - "id" : "js/disabling-electron-websecurity", + "tags" : [ "maintainability", "security", "external/cwe/cwe-200", "external/cwe/cwe-1022" ], + "description" : "External links that open in a new tab or window but do not specify\n link type 'noopener' or 'noreferrer' are a potential security risk.", + "id" : "js/unsafe-external-link", "kind" : "problem", - "name" : "Disabling Electron webSecurity", + "name" : "Potentially unsafe external link", "precision" : "very-high", - "problem.severity" : "error", - "security-severity" : "6.1" + "problem.severity" : "warning", + "security-severity" : "6.5" } }, { - "id" : "js/enabling-electron-insecure-content", - "name" : "js/enabling-electron-insecure-content", + "id" : "js/clear-text-cookie", + "name" : "js/clear-text-cookie", "shortDescription" : { - "text" : "Enabling Electron allowRunningInsecureContent" + "text" : "Clear text transmission of sensitive cookie" }, "fullDescription" : { - "text" : "Enabling allowRunningInsecureContent can allow remote code execution." + "text" : "Sending sensitive information in a cookie without requring SSL encryption can expose the cookie to an attacker." }, "defaultConfiguration" : { "enabled" : true, - "level" : "error" + "level" : "warning" }, "help" : { - "text" : "# Enabling Electron allowRunningInsecureContent\nElectron is secure by default through a policy banning the execution of content loaded over HTTP. Setting the `allowRunningInsecureContent` property of a `webPreferences` object to `true` will disable this policy.\n\nEnabling the execution of insecure content is strongly discouraged.\n\n\n## Recommendation\nDo not enable the `allowRunningInsecureContent` property.\n\n\n## Example\nThe following example shows `allowRunningInsecureContent` being enabled.\n\n\n```javascript\nconst mainWindow = new BrowserWindow({\n webPreferences: {\n allowRunningInsecureContent: true\n }\n})\n```\nThis is problematic, since it allows the execution of code from an untrusted origin.\n\n\n## References\n* Electron Documentation: [Security, Native Capabilities, and Your Responsibility](https://electronjs.org/docs/tutorial/security#8-do-not-set-allowrunninginsecurecontent-to-true)\n* Common Weakness Enumeration: [CWE-494](https://cwe.mitre.org/data/definitions/494.html).\n", - "markdown" : "# Enabling Electron allowRunningInsecureContent\nElectron is secure by default through a policy banning the execution of content loaded over HTTP. Setting the `allowRunningInsecureContent` property of a `webPreferences` object to `true` will disable this policy.\n\nEnabling the execution of insecure content is strongly discouraged.\n\n\n## Recommendation\nDo not enable the `allowRunningInsecureContent` property.\n\n\n## Example\nThe following example shows `allowRunningInsecureContent` being enabled.\n\n\n```javascript\nconst mainWindow = new BrowserWindow({\n webPreferences: {\n allowRunningInsecureContent: true\n }\n})\n```\nThis is problematic, since it allows the execution of code from an untrusted origin.\n\n\n## References\n* Electron Documentation: [Security, Native Capabilities, and Your Responsibility](https://electronjs.org/docs/tutorial/security#8-do-not-set-allowrunninginsecurecontent-to-true)\n* Common Weakness Enumeration: [CWE-494](https://cwe.mitre.org/data/definitions/494.html).\n" + "text" : "# Clear text transmission of sensitive cookie\nCookies that are transmitted in clear text can be intercepted by an attacker. If sensitive cookies are intercepted, the attacker can read the cookie and use it to perform actions on the user's behalf.\n\n\n## Recommendation\nAlways transmit sensitive cookies using SSL by setting the `secure` attribute on the cookie.\n\n\n## Example\nThe following example stores an authentication token in a cookie that can be transmitted in clear text.\n\n\n```javascript\nconst http = require('http');\n\nconst server = http.createServer((req, res) => {\n res.setHeader(\"Set-Cookie\", `authKey=${makeAuthkey()}`);\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('

Hello world

');\n});\n```\nTo force the cookie to be transmitted using SSL, set the `secure` attribute on the cookie.\n\n\n```javascript\nconst http = require('http');\n\nconst server = http.createServer((req, res) => {\n res.setHeader(\"Set-Cookie\", `authKey=${makeAuthkey()}; secure; httpOnly`);\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('

Hello world

');\n});\n```\n\n## References\n* ExpressJS: [Use cookies securely](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely).\n* OWASP: [Set cookie flags appropriately](https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#set-cookie-flags-appropriately).\n* Mozilla: [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie).\n* Common Weakness Enumeration: [CWE-614](https://cwe.mitre.org/data/definitions/614.html).\n* Common Weakness Enumeration: [CWE-311](https://cwe.mitre.org/data/definitions/311.html).\n* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html).\n* Common Weakness Enumeration: [CWE-319](https://cwe.mitre.org/data/definitions/319.html).\n", + "markdown" : "# Clear text transmission of sensitive cookie\nCookies that are transmitted in clear text can be intercepted by an attacker. If sensitive cookies are intercepted, the attacker can read the cookie and use it to perform actions on the user's behalf.\n\n\n## Recommendation\nAlways transmit sensitive cookies using SSL by setting the `secure` attribute on the cookie.\n\n\n## Example\nThe following example stores an authentication token in a cookie that can be transmitted in clear text.\n\n\n```javascript\nconst http = require('http');\n\nconst server = http.createServer((req, res) => {\n res.setHeader(\"Set-Cookie\", `authKey=${makeAuthkey()}`);\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('

Hello world

');\n});\n```\nTo force the cookie to be transmitted using SSL, set the `secure` attribute on the cookie.\n\n\n```javascript\nconst http = require('http');\n\nconst server = http.createServer((req, res) => {\n res.setHeader(\"Set-Cookie\", `authKey=${makeAuthkey()}; secure; httpOnly`);\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('

Hello world

');\n});\n```\n\n## References\n* ExpressJS: [Use cookies securely](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely).\n* OWASP: [Set cookie flags appropriately](https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#set-cookie-flags-appropriately).\n* Mozilla: [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie).\n* Common Weakness Enumeration: [CWE-614](https://cwe.mitre.org/data/definitions/614.html).\n* Common Weakness Enumeration: [CWE-311](https://cwe.mitre.org/data/definitions/311.html).\n* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html).\n* Common Weakness Enumeration: [CWE-319](https://cwe.mitre.org/data/definitions/319.html).\n" }, "properties" : { - "tags" : [ "security", "frameworks/electron", "external/cwe/cwe-494" ], - "description" : "Enabling allowRunningInsecureContent can allow remote code execution.", - "id" : "js/enabling-electron-insecure-content", + "tags" : [ "security", "external/cwe/cwe-614", "external/cwe/cwe-311", "external/cwe/cwe-312", "external/cwe/cwe-319" ], + "description" : "Sending sensitive information in a cookie without requring SSL encryption\n can expose the cookie to an attacker.", + "id" : "js/clear-text-cookie", "kind" : "problem", - "name" : "Enabling Electron allowRunningInsecureContent", - "precision" : "very-high", - "problem.severity" : "error", - "security-severity" : "8.8" + "name" : "Clear text transmission of sensitive cookie", + "precision" : "high", + "problem.severity" : "warning", + "security-severity" : "5.0" } }, { - "id" : "js/unsafe-external-link", - "name" : "js/unsafe-external-link", + "id" : "js/incomplete-sanitization", + "name" : "js/incomplete-sanitization", "shortDescription" : { - "text" : "Potentially unsafe external link" + "text" : "Incomplete string escaping or encoding" }, "fullDescription" : { - "text" : "External links that open in a new tab or window but do not specify link type 'noopener' or 'noreferrer' are a potential security risk." + "text" : "A string transformer that does not replace or escape all occurrences of a meta-character may be ineffective." }, "defaultConfiguration" : { "enabled" : true, "level" : "warning" }, "help" : { - "text" : "# Potentially unsafe external link\nHTML links that open in a new tab or window allow the target page to access the DOM of the origin page using `window.opener` unless link type `noopener` or `noreferrer` is specified. This is a potential security risk.\n\n\n## Recommendation\nSpecify the link type by adding an attribute `rel=\"noopener noreferrer\"`.\n\n\n## Example\nIn the following example, a JSX element is created that corresponds to an HTML link opening the URL `http://example.com` in a new tab. Since it does not specify a link type, that page will be able to access the DOM of the origin page.\n\n\n```javascript\nvar link = Example;\n\n```\nTo fix this vulnerability, add a `rel` attribute:\n\n\n```javascript\nvar link = Example;\n\n```\n\n## References\n* Mathias Bynens: [About rel=noopener](https://mathiasbynens.github.io/rel-noopener/).\n* Mozilla Developer Network: [HTML Anchor Element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a).\n* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html).\n* Common Weakness Enumeration: [CWE-1022](https://cwe.mitre.org/data/definitions/1022.html).\n", - "markdown" : "# Potentially unsafe external link\nHTML links that open in a new tab or window allow the target page to access the DOM of the origin page using `window.opener` unless link type `noopener` or `noreferrer` is specified. This is a potential security risk.\n\n\n## Recommendation\nSpecify the link type by adding an attribute `rel=\"noopener noreferrer\"`.\n\n\n## Example\nIn the following example, a JSX element is created that corresponds to an HTML link opening the URL `http://example.com` in a new tab. Since it does not specify a link type, that page will be able to access the DOM of the origin page.\n\n\n```javascript\nvar link = Example;\n\n```\nTo fix this vulnerability, add a `rel` attribute:\n\n\n```javascript\nvar link = Example;\n\n```\n\n## References\n* Mathias Bynens: [About rel=noopener](https://mathiasbynens.github.io/rel-noopener/).\n* Mozilla Developer Network: [HTML Anchor Element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a).\n* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html).\n* Common Weakness Enumeration: [CWE-1022](https://cwe.mitre.org/data/definitions/1022.html).\n" + "text" : "# Incomplete string escaping or encoding\nSanitizing untrusted input is a common technique for preventing injection attacks such as SQL injection or cross-site scripting. Usually, this is done by escaping meta-characters such as quotes in a domain-specific way so that they are treated as normal characters.\n\nHowever, directly using the string `replace` method to perform escaping is notoriously error-prone. Common mistakes include only replacing the first occurrence of a meta-character, or backslash-escaping various meta-characters but not the backslash itself.\n\nIn the former case, later meta-characters are left undisturbed and can be used to subvert the sanitization. In the latter case, preceding a meta-character with a backslash leads to the backslash being escaped, but the meta-character appearing un-escaped, which again makes the sanitization ineffective.\n\nEven if the escaped string is not used in a security-critical context, incomplete escaping may still have undesirable effects, such as badly rendered or confusing output.\n\n\n## Recommendation\nUse a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation.\n\nAn even safer alternative is to design the application so that sanitization is not needed, for instance by using prepared statements for SQL queries.\n\nOtherwise, make sure to use a regular expression with the `g` flag to ensure that all occurrences are replaced, and remember to escape backslashes if applicable.\n\n\n## Example\nFor example, assume that we want to embed a user-controlled string `accountNumber` into a SQL query as part of a string literal. To avoid SQL injection, we need to ensure that the string does not contain un-escaped single-quote characters. The following function attempts to ensure this by doubling single quotes, and thereby escaping them:\n\n\n```javascript\nfunction escapeQuotes(s) {\n return s.replace(\"'\", \"''\");\n}\n\n```\nAs written, this sanitizer is ineffective: if the first argument to `replace` is a string literal (as in this case), only the *first* occurrence of that string is replaced.\n\nAs mentioned above, the function `escapeQuotes` should be replaced with a purpose-built sanitization library, such as the npm module `sqlstring`. Many other sanitization libraries are available from npm and other sources.\n\nIf this is not an option, `escapeQuotes` should be rewritten to use a regular expression with the `g` (\"global\") flag instead:\n\n\n```javascript\nfunction escapeQuotes(s) {\n return s.replace(/'/g, \"''\");\n}\n\n```\nNote that it is very important to include the global flag: `s.replace(/'/, \"''\")` *without* the global flag is equivalent to the first example above and only replaces the first quote.\n\n\n## References\n* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection).\n* npm: [sqlstring](https://www.npmjs.com/package/sqlstring) package.\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n* Common Weakness Enumeration: [CWE-80](https://cwe.mitre.org/data/definitions/80.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n", + "markdown" : "# Incomplete string escaping or encoding\nSanitizing untrusted input is a common technique for preventing injection attacks such as SQL injection or cross-site scripting. Usually, this is done by escaping meta-characters such as quotes in a domain-specific way so that they are treated as normal characters.\n\nHowever, directly using the string `replace` method to perform escaping is notoriously error-prone. Common mistakes include only replacing the first occurrence of a meta-character, or backslash-escaping various meta-characters but not the backslash itself.\n\nIn the former case, later meta-characters are left undisturbed and can be used to subvert the sanitization. In the latter case, preceding a meta-character with a backslash leads to the backslash being escaped, but the meta-character appearing un-escaped, which again makes the sanitization ineffective.\n\nEven if the escaped string is not used in a security-critical context, incomplete escaping may still have undesirable effects, such as badly rendered or confusing output.\n\n\n## Recommendation\nUse a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation.\n\nAn even safer alternative is to design the application so that sanitization is not needed, for instance by using prepared statements for SQL queries.\n\nOtherwise, make sure to use a regular expression with the `g` flag to ensure that all occurrences are replaced, and remember to escape backslashes if applicable.\n\n\n## Example\nFor example, assume that we want to embed a user-controlled string `accountNumber` into a SQL query as part of a string literal. To avoid SQL injection, we need to ensure that the string does not contain un-escaped single-quote characters. The following function attempts to ensure this by doubling single quotes, and thereby escaping them:\n\n\n```javascript\nfunction escapeQuotes(s) {\n return s.replace(\"'\", \"''\");\n}\n\n```\nAs written, this sanitizer is ineffective: if the first argument to `replace` is a string literal (as in this case), only the *first* occurrence of that string is replaced.\n\nAs mentioned above, the function `escapeQuotes` should be replaced with a purpose-built sanitization library, such as the npm module `sqlstring`. Many other sanitization libraries are available from npm and other sources.\n\nIf this is not an option, `escapeQuotes` should be rewritten to use a regular expression with the `g` (\"global\") flag instead:\n\n\n```javascript\nfunction escapeQuotes(s) {\n return s.replace(/'/g, \"''\");\n}\n\n```\nNote that it is very important to include the global flag: `s.replace(/'/, \"''\")` *without* the global flag is equivalent to the first example above and only replaces the first quote.\n\n\n## References\n* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection).\n* npm: [sqlstring](https://www.npmjs.com/package/sqlstring) package.\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n* Common Weakness Enumeration: [CWE-80](https://cwe.mitre.org/data/definitions/80.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n" }, "properties" : { - "tags" : [ "maintainability", "security", "external/cwe/cwe-200", "external/cwe/cwe-1022" ], - "description" : "External links that open in a new tab or window but do not specify\n link type 'noopener' or 'noreferrer' are a potential security risk.", - "id" : "js/unsafe-external-link", + "tags" : [ "correctness", "security", "external/cwe/cwe-020", "external/cwe/cwe-080", "external/cwe/cwe-116" ], + "description" : "A string transformer that does not replace or escape all occurrences of a\n meta-character may be ineffective.", + "id" : "js/incomplete-sanitization", "kind" : "problem", - "name" : "Potentially unsafe external link", - "precision" : "very-high", + "name" : "Incomplete string escaping or encoding", + "precision" : "high", "problem.severity" : "warning", - "security-severity" : "6.5" + "security-severity" : "7.8" } }, { - "id" : "js/angular/double-compilation", - "name" : "js/angular/double-compilation", + "id" : "js/unsafe-html-expansion", + "name" : "js/unsafe-html-expansion", "shortDescription" : { - "text" : "Double compilation" + "text" : "Unsafe expansion of self-closing HTML tag" }, "fullDescription" : { - "text" : "Recompiling an already compiled part of the DOM can lead to unexpected behavior of directives, performance problems, and memory leaks." + "text" : "Using regular expressions to expand self-closing HTML tags may lead to cross-site scripting vulnerabilities." }, "defaultConfiguration" : { "enabled" : true, "level" : "warning" }, "help" : { - "text" : "# Double compilation\nThe AngularJS compiler processes (parts of) the DOM, determining which directives match which DOM elements, and then applies the directives to the elements. Each DOM element should only be compiled once, otherwise unexpected behavior may result.\n\n\n## Recommendation\nOnly compile new DOM elements.\n\n\n## Example\nThe following example (adapted from the AngularJS developer guide) shows a directive that adds a tooltip to a DOM element, and then compiles the entire element to apply nested directives.\n\n\n```javascript\nangular.module('myapp')\n .directive('addToolTip', function($compile) {\n return {\n link: function(scope, element, attrs) {\n var tooltip = angular.element('A tooltip');\n tooltip.on('mouseenter mouseleave', function() {\n scope.$apply('showToolTip = !showToolTip');\n });\n element.append(tooltip);\n $compile(element)(scope); // NOT OK\n }\n };\n});\n\n```\nThis is problematic, since it will recompile all of `element`, including parts that have already been compiled.\n\nInstead, only the new element should be compiled:\n\n\n```javascript\nangular.module('myapp')\n .directive('addToolTip', function($compile) {\n return {\n link: function(scope, element, attrs) {\n var tooltip = angular.element('A tooltip');\n tooltip.on('mouseenter mouseleave', function() {\n scope.$apply('showToolTip = !showToolTip');\n });\n element.append(tooltip);\n $compile(tooltip)(scope); // OK\n }\n };\n});\n\n```\n\n## References\n* AngularJS Developer Guide: [Double Compilation, and how to avoid it](https://docs.angularjs.org/guide/compiler#double-compilation-and-how-to-avoid-it).\n* Common Weakness Enumeration: [CWE-1176](https://cwe.mitre.org/data/definitions/1176.html).\n", - "markdown" : "# Double compilation\nThe AngularJS compiler processes (parts of) the DOM, determining which directives match which DOM elements, and then applies the directives to the elements. Each DOM element should only be compiled once, otherwise unexpected behavior may result.\n\n\n## Recommendation\nOnly compile new DOM elements.\n\n\n## Example\nThe following example (adapted from the AngularJS developer guide) shows a directive that adds a tooltip to a DOM element, and then compiles the entire element to apply nested directives.\n\n\n```javascript\nangular.module('myapp')\n .directive('addToolTip', function($compile) {\n return {\n link: function(scope, element, attrs) {\n var tooltip = angular.element('A tooltip');\n tooltip.on('mouseenter mouseleave', function() {\n scope.$apply('showToolTip = !showToolTip');\n });\n element.append(tooltip);\n $compile(element)(scope); // NOT OK\n }\n };\n});\n\n```\nThis is problematic, since it will recompile all of `element`, including parts that have already been compiled.\n\nInstead, only the new element should be compiled:\n\n\n```javascript\nangular.module('myapp')\n .directive('addToolTip', function($compile) {\n return {\n link: function(scope, element, attrs) {\n var tooltip = angular.element('A tooltip');\n tooltip.on('mouseenter mouseleave', function() {\n scope.$apply('showToolTip = !showToolTip');\n });\n element.append(tooltip);\n $compile(tooltip)(scope); // OK\n }\n };\n});\n\n```\n\n## References\n* AngularJS Developer Guide: [Double Compilation, and how to avoid it](https://docs.angularjs.org/guide/compiler#double-compilation-and-how-to-avoid-it).\n* Common Weakness Enumeration: [CWE-1176](https://cwe.mitre.org/data/definitions/1176.html).\n" + "text" : "# Unsafe expansion of self-closing HTML tag\nSanitizing untrusted input for HTML meta-characters is a common technique for preventing cross-site scripting attacks. But even a sanitized input can be dangerous to use if it is modified further before a browser treats it as HTML. A seemingly innocent transformation that expands a self-closing HTML tag from `
` to `
` may in fact cause cross-site scripting vulnerabilities.\n\n\n## Recommendation\nUse a well-tested sanitization library if at all possible, and avoid modifying sanitized values further before treating them as HTML.\n\nAn even safer alternative is to design the application so that sanitization is not needed, for instance by using HTML templates that are explicit about the values they treat as HTML.\n\n\n## Example\nThe following function transforms a self-closing HTML tag to a pair of open/close tags. It does so for all non-`img` and non-`area` tags, by using a regular expression with two capture groups. The first capture group corresponds to the name of the tag, and the second capture group to the content of the tag.\n\n\n```javascript\nfunction expandSelfClosingTags(html) {\n\tvar rxhtmlTag = /<(?!img|area)(([a-z][^\\w\\/>]*)[^>]*)\\/>/gi;\n\treturn html.replace(rxhtmlTag, \"<$1>\"); // BAD\n}\n\n```\nWhile it is generally known regular expressions are ill-suited for parsing HTML, variants of this particular transformation pattern have long been considered safe.\n\nHowever, the function is not safe. As an example, consider the following string:\n\n\n```html\n
\n\"/>\n\n```\nWhen the above function transforms the string, it becomes a string that results in an alert when a browser treats it as HTML.\n\n\n```html\n
\n\"/>\n\n```\n\n## References\n* jQuery: [Security fixes in jQuery 3.5.0](https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/)\n* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html).\n* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).\n* OWASP [Types of Cross-Site](https://owasp.org/www-community/Types_of_Cross-Site_Scripting).\n* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting).\n* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n", + "markdown" : "# Unsafe expansion of self-closing HTML tag\nSanitizing untrusted input for HTML meta-characters is a common technique for preventing cross-site scripting attacks. But even a sanitized input can be dangerous to use if it is modified further before a browser treats it as HTML. A seemingly innocent transformation that expands a self-closing HTML tag from `
` to `
` may in fact cause cross-site scripting vulnerabilities.\n\n\n## Recommendation\nUse a well-tested sanitization library if at all possible, and avoid modifying sanitized values further before treating them as HTML.\n\nAn even safer alternative is to design the application so that sanitization is not needed, for instance by using HTML templates that are explicit about the values they treat as HTML.\n\n\n## Example\nThe following function transforms a self-closing HTML tag to a pair of open/close tags. It does so for all non-`img` and non-`area` tags, by using a regular expression with two capture groups. The first capture group corresponds to the name of the tag, and the second capture group to the content of the tag.\n\n\n```javascript\nfunction expandSelfClosingTags(html) {\n\tvar rxhtmlTag = /<(?!img|area)(([a-z][^\\w\\/>]*)[^>]*)\\/>/gi;\n\treturn html.replace(rxhtmlTag, \"<$1>\"); // BAD\n}\n\n```\nWhile it is generally known regular expressions are ill-suited for parsing HTML, variants of this particular transformation pattern have long been considered safe.\n\nHowever, the function is not safe. As an example, consider the following string:\n\n\n```html\n
\n\"/>\n\n```\nWhen the above function transforms the string, it becomes a string that results in an alert when a browser treats it as HTML.\n\n\n```html\n
\n\"/>\n\n```\n\n## References\n* jQuery: [Security fixes in jQuery 3.5.0](https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/)\n* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html).\n* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).\n* OWASP [Types of Cross-Site](https://owasp.org/www-community/Types_of_Cross-Site_Scripting).\n* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting).\n* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n" }, "properties" : { - "tags" : [ "reliability", "frameworks/angularjs", "security", "external/cwe/cwe-1176" ], - "description" : "Recompiling an already compiled part of the DOM can lead to\n unexpected behavior of directives, performance problems, and memory leaks.", - "id" : "js/angular/double-compilation", + "tags" : [ "correctness", "security", "external/cwe/cwe-079", "external/cwe/cwe-116" ], + "description" : "Using regular expressions to expand self-closing HTML\n tags may lead to cross-site scripting vulnerabilities.", + "id" : "js/unsafe-html-expansion", "kind" : "problem", - "name" : "Double compilation", + "name" : "Unsafe expansion of self-closing HTML tag", "precision" : "very-high", "problem.severity" : "warning", - "security-severity" : "8.8" + "security-severity" : "6.1" } }, { - "id" : "js/angular/insecure-url-whitelist", - "name" : "js/angular/insecure-url-whitelist", + "id" : "js/bad-tag-filter", + "name" : "js/bad-tag-filter", "shortDescription" : { - "text" : "Insecure URL whitelist" + "text" : "Bad HTML filtering regexp" }, "fullDescription" : { - "text" : "URL whitelists that are too permissive can cause security vulnerabilities." + "text" : "Matching HTML tags using regular expressions is hard to do right, and can easily lead to security issues." }, "defaultConfiguration" : { "enabled" : true, "level" : "warning" }, "help" : { - "text" : "# Insecure URL whitelist\nAngularJS uses filters to ensure that the URLs used for sourcing AngularJS templates and other script-running URLs are safe. One such filter is a whitelist of URL patterns to allow.\n\nA URL pattern that is too permissive can cause security vulnerabilities.\n\n\n## Recommendation\nMake the whitelist URL patterns as restrictive as possible.\n\n\n## Example\nThe following example shows an AngularJS application with whitelist URL patterns that all are too permissive.\n\n\n```javascript\nangular.module('myApp', [])\n .config(function($sceDelegateProvider) {\n $sceDelegateProvider.resourceUrlWhitelist([\n \"*://example.org/*\", // BAD\n \"https://**.example.com/*\", // BAD\n \"https://example.**\", // BAD\n \"https://example.*\" // BAD\n ]);\n });\n\n```\nThis is problematic, since the four patterns match the following malicious URLs, respectively:\n\n* `javascript://example.org/a%0A%0Dalert(1)` (`%0A%0D` is a linebreak)\n* `https://evil.com/?ignore=://example.com/a`\n* `https://example.evil.com`\n* `https://example.evilTld`\n\n## References\n* OWASP/Google presentation: [Securing AngularJS Applications](https://www.owasp.org/images/6/6e/Benelus_day_20161125_S_Lekies_Securing_AngularJS_Applications.pdf)\n* AngularJS Developer Guide: [Format of items in resourceUrlWhitelist/Blacklist](https://docs.angularjs.org/api/ng/service/$sce#resourceUrlPatternItem).\n* Common Weakness Enumeration: [CWE-183](https://cwe.mitre.org/data/definitions/183.html).\n* Common Weakness Enumeration: [CWE-625](https://cwe.mitre.org/data/definitions/625.html).\n", - "markdown" : "# Insecure URL whitelist\nAngularJS uses filters to ensure that the URLs used for sourcing AngularJS templates and other script-running URLs are safe. One such filter is a whitelist of URL patterns to allow.\n\nA URL pattern that is too permissive can cause security vulnerabilities.\n\n\n## Recommendation\nMake the whitelist URL patterns as restrictive as possible.\n\n\n## Example\nThe following example shows an AngularJS application with whitelist URL patterns that all are too permissive.\n\n\n```javascript\nangular.module('myApp', [])\n .config(function($sceDelegateProvider) {\n $sceDelegateProvider.resourceUrlWhitelist([\n \"*://example.org/*\", // BAD\n \"https://**.example.com/*\", // BAD\n \"https://example.**\", // BAD\n \"https://example.*\" // BAD\n ]);\n });\n\n```\nThis is problematic, since the four patterns match the following malicious URLs, respectively:\n\n* `javascript://example.org/a%0A%0Dalert(1)` (`%0A%0D` is a linebreak)\n* `https://evil.com/?ignore=://example.com/a`\n* `https://example.evil.com`\n* `https://example.evilTld`\n\n## References\n* OWASP/Google presentation: [Securing AngularJS Applications](https://www.owasp.org/images/6/6e/Benelus_day_20161125_S_Lekies_Securing_AngularJS_Applications.pdf)\n* AngularJS Developer Guide: [Format of items in resourceUrlWhitelist/Blacklist](https://docs.angularjs.org/api/ng/service/$sce#resourceUrlPatternItem).\n* Common Weakness Enumeration: [CWE-183](https://cwe.mitre.org/data/definitions/183.html).\n* Common Weakness Enumeration: [CWE-625](https://cwe.mitre.org/data/definitions/625.html).\n" + "text" : "# Bad HTML filtering regexp\nIt is possible to match some single HTML tags using regular expressions (parsing general HTML using regular expressions is impossible). However, if the regular expression is not written well it might be possible to circumvent it, which can lead to cross-site scripting or other security issues.\n\nSome of these mistakes are caused by browsers having very forgiving HTML parsers, and will often render invalid HTML containing syntax errors. Regular expressions that attempt to match HTML should also recognize tags containing such syntax errors.\n\n\n## Recommendation\nUse a well-tested sanitization or parser library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation.\n\n\n## Example\nThe following example attempts to filters out all `` as script end tags, but also tags such as `` even though it is a parser error. This means that an attack string such as `` will not be filtered by the function, and `alert(1)` will be executed by a browser if the string is rendered as HTML.\n\nOther corner cases include that HTML comments can end with `--!>`, and that HTML tag names can contain upper case characters.\n\n\n## References\n* Securitum: [The Curious Case of Copy & Paste](https://research.securitum.com/the-curious-case-of-copy-paste/).\n* stackoverflow.com: [You can't parse \\[X\\]HTML with regex](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags#answer-1732454).\n* HTML Standard: [Comment end bang state](https://html.spec.whatwg.org/multipage/parsing.html#comment-end-bang-state).\n* stackoverflow.com: [Why aren't browsers strict about HTML?](https://stackoverflow.com/questions/25559999/why-arent-browsers-strict-about-html).\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n* Common Weakness Enumeration: [CWE-80](https://cwe.mitre.org/data/definitions/80.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n* Common Weakness Enumeration: [CWE-184](https://cwe.mitre.org/data/definitions/184.html).\n* Common Weakness Enumeration: [CWE-185](https://cwe.mitre.org/data/definitions/185.html).\n* Common Weakness Enumeration: [CWE-186](https://cwe.mitre.org/data/definitions/186.html).\n", + "markdown" : "# Bad HTML filtering regexp\nIt is possible to match some single HTML tags using regular expressions (parsing general HTML using regular expressions is impossible). However, if the regular expression is not written well it might be possible to circumvent it, which can lead to cross-site scripting or other security issues.\n\nSome of these mistakes are caused by browsers having very forgiving HTML parsers, and will often render invalid HTML containing syntax errors. Regular expressions that attempt to match HTML should also recognize tags containing such syntax errors.\n\n\n## Recommendation\nUse a well-tested sanitization or parser library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation.\n\n\n## Example\nThe following example attempts to filters out all `` as script end tags, but also tags such as `` even though it is a parser error. This means that an attack string such as `` will not be filtered by the function, and `alert(1)` will be executed by a browser if the string is rendered as HTML.\n\nOther corner cases include that HTML comments can end with `--!>`, and that HTML tag names can contain upper case characters.\n\n\n## References\n* Securitum: [The Curious Case of Copy & Paste](https://research.securitum.com/the-curious-case-of-copy-paste/).\n* stackoverflow.com: [You can't parse \\[X\\]HTML with regex](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags#answer-1732454).\n* HTML Standard: [Comment end bang state](https://html.spec.whatwg.org/multipage/parsing.html#comment-end-bang-state).\n* stackoverflow.com: [Why aren't browsers strict about HTML?](https://stackoverflow.com/questions/25559999/why-arent-browsers-strict-about-html).\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n* Common Weakness Enumeration: [CWE-80](https://cwe.mitre.org/data/definitions/80.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n* Common Weakness Enumeration: [CWE-184](https://cwe.mitre.org/data/definitions/184.html).\n* Common Weakness Enumeration: [CWE-185](https://cwe.mitre.org/data/definitions/185.html).\n* Common Weakness Enumeration: [CWE-186](https://cwe.mitre.org/data/definitions/186.html).\n" }, "properties" : { - "tags" : [ "security", "frameworks/angularjs", "external/cwe/cwe-183", "external/cwe/cwe-625" ], - "description" : "URL whitelists that are too permissive can cause security vulnerabilities.", - "id" : "js/angular/insecure-url-whitelist", + "tags" : [ "correctness", "security", "external/cwe/cwe-020", "external/cwe/cwe-080", "external/cwe/cwe-116", "external/cwe/cwe-184", "external/cwe/cwe-185", "external/cwe/cwe-186" ], + "description" : "Matching HTML tags using regular expressions is hard to do right, and can easily lead to security issues.", + "id" : "js/bad-tag-filter", "kind" : "problem", - "name" : "Insecure URL whitelist", - "precision" : "very-high", + "name" : "Bad HTML filtering regexp", + "precision" : "high", "problem.severity" : "warning", - "security-severity" : "7.5" + "security-severity" : "7.8" } }, { - "id" : "js/angular/disabling-sce", - "name" : "js/angular/disabling-sce", + "id" : "js/double-escaping", + "name" : "js/double-escaping", "shortDescription" : { - "text" : "Disabling SCE" + "text" : "Double escaping or unescaping" }, "fullDescription" : { - "text" : "Disabling strict contextual escaping (SCE) can cause security vulnerabilities." + "text" : "When escaping special characters using a meta-character like backslash or ampersand, the meta-character has to be escaped first to avoid double-escaping, and conversely it has to be unescaped last to avoid double-unescaping." }, "defaultConfiguration" : { "enabled" : true, "level" : "warning" }, "help" : { - "text" : "# Disabling SCE\nAngularJS is secure by default through automated sanitization and filtering of untrusted values that could cause vulnerabilities such as XSS. Strict Contextual Escaping (SCE) is an execution mode in AngularJS that provides this security mechanism.\n\nDisabling SCE in an AngularJS application is strongly discouraged. It is even more discouraged to disable SCE in a library, since it is an application-wide setting.\n\n\n## Recommendation\nDo not disable SCE.\n\n\n## Example\nThe following example shows an AngularJS application that disables SCE in order to dynamically construct an HTML fragment, which is later inserted into the DOM through `$scope.html`.\n\n\n```javascript\nangular.module('app', [])\n .config(function($sceProvider) {\n $sceProvider.enabled(false); // BAD\n }).controller('controller', function($scope) {\n // ...\n $scope.html = '
  • ' + item.toString() + '
';\n });\n\n```\nThis is problematic, since it disables SCE for the entire AngularJS application.\n\nInstead, just mark the dynamically constructed HTML fragment as safe using `$sce.trustAsHtml`, before assigning it to `$scope.html`:\n\n\n```javascript\nangular.module('app', [])\n .controller('controller', function($scope, $sce) {\n // ...\n // GOOD (but should use the templating system instead)\n $scope.html = $sce.trustAsHtml('
  • ' + item.toString() + '
'); \n });\n\n```\nPlease note that this example is for illustrative purposes only; use the AngularJS templating system to dynamically construct HTML when possible.\n\n\n## References\n* AngularJS Developer Guide: [Strict Contextual Escaping](https://docs.angularjs.org/api/ng/service/$sce)\n* AngularJS Developer Guide: [Can I disable SCE completely?](https://docs.angularjs.org/api/ng/service/$sce#can-i-disable-sce-completely-).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n", - "markdown" : "# Disabling SCE\nAngularJS is secure by default through automated sanitization and filtering of untrusted values that could cause vulnerabilities such as XSS. Strict Contextual Escaping (SCE) is an execution mode in AngularJS that provides this security mechanism.\n\nDisabling SCE in an AngularJS application is strongly discouraged. It is even more discouraged to disable SCE in a library, since it is an application-wide setting.\n\n\n## Recommendation\nDo not disable SCE.\n\n\n## Example\nThe following example shows an AngularJS application that disables SCE in order to dynamically construct an HTML fragment, which is later inserted into the DOM through `$scope.html`.\n\n\n```javascript\nangular.module('app', [])\n .config(function($sceProvider) {\n $sceProvider.enabled(false); // BAD\n }).controller('controller', function($scope) {\n // ...\n $scope.html = '
  • ' + item.toString() + '
';\n });\n\n```\nThis is problematic, since it disables SCE for the entire AngularJS application.\n\nInstead, just mark the dynamically constructed HTML fragment as safe using `$sce.trustAsHtml`, before assigning it to `$scope.html`:\n\n\n```javascript\nangular.module('app', [])\n .controller('controller', function($scope, $sce) {\n // ...\n // GOOD (but should use the templating system instead)\n $scope.html = $sce.trustAsHtml('
  • ' + item.toString() + '
'); \n });\n\n```\nPlease note that this example is for illustrative purposes only; use the AngularJS templating system to dynamically construct HTML when possible.\n\n\n## References\n* AngularJS Developer Guide: [Strict Contextual Escaping](https://docs.angularjs.org/api/ng/service/$sce)\n* AngularJS Developer Guide: [Can I disable SCE completely?](https://docs.angularjs.org/api/ng/service/$sce#can-i-disable-sce-completely-).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n" + "text" : "# Double escaping or unescaping\nEscaping meta-characters in untrusted input is an important technique for preventing injection attacks such as cross-site scripting. One particular example of this is HTML entity encoding, where HTML special characters are replaced by HTML character entities to prevent them from being interpreted as HTML markup. For example, the less-than character is encoded as `<` and the double-quote character as `"`. Other examples include backslash-escaping for including untrusted data in string literals and percent-encoding for URI components.\n\nThe reverse process of replacing escape sequences with the characters they represent is known as unescaping.\n\nNote that the escape characters themselves (such as ampersand in the case of HTML encoding) play a special role during escaping and unescaping: they are themselves escaped, but also form part of the escaped representations of other characters. Hence care must be taken to avoid double escaping and unescaping: when escaping, the escape character must be escaped first, when unescaping it has to be unescaped last.\n\nIf used in the context of sanitization, double unescaping may render the sanitization ineffective. Even if it is not used in a security-critical context, it may still result in confusing or garbled output.\n\n\n## Recommendation\nUse a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation. For URI encoding, you can use the standard `encodeURIComponent` and `decodeURIComponent` functions.\n\nOtherwise, make sure to always escape the escape character first, and unescape it last.\n\n\n## Example\nThe following example shows a pair of hand-written HTML encoding and decoding functions:\n\n\n```javascript\nmodule.exports.encode = function(s) {\n return s.replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n};\n\nmodule.exports.decode = function(s) {\n return s.replace(/&/g, \"&\")\n .replace(/"/g, \"\\\"\")\n .replace(/'/g, \"'\");\n};\n\n```\nThe encoding function correctly handles ampersand before the other characters. For example, the string `me & \"you\"` is encoded as `me & "you"`, and the string `"` is encoded as `&quot;`.\n\nThe decoding function, however, incorrectly decodes `&` into `&` before handling the other characters. So while it correctly decodes the first example above, it decodes the second example (`&quot;`) to `\"` (a single double quote), which is not correct.\n\nInstead, the decoding function should decode the ampersand last:\n\n\n```javascript\nmodule.exports.encode = function(s) {\n return s.replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n};\n\nmodule.exports.decode = function(s) {\n return s.replace(/"/g, \"\\\"\")\n .replace(/'/g, \"'\")\n .replace(/&/g, \"&\");\n};\n\n```\n\n## References\n* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection).\n* npm: [html-entities](https://www.npmjs.com/package/html-entities) package.\n* npm: [js-string-escape](https://www.npmjs.com/package/js-string-escape) package.\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n", + "markdown" : "# Double escaping or unescaping\nEscaping meta-characters in untrusted input is an important technique for preventing injection attacks such as cross-site scripting. One particular example of this is HTML entity encoding, where HTML special characters are replaced by HTML character entities to prevent them from being interpreted as HTML markup. For example, the less-than character is encoded as `<` and the double-quote character as `"`. Other examples include backslash-escaping for including untrusted data in string literals and percent-encoding for URI components.\n\nThe reverse process of replacing escape sequences with the characters they represent is known as unescaping.\n\nNote that the escape characters themselves (such as ampersand in the case of HTML encoding) play a special role during escaping and unescaping: they are themselves escaped, but also form part of the escaped representations of other characters. Hence care must be taken to avoid double escaping and unescaping: when escaping, the escape character must be escaped first, when unescaping it has to be unescaped last.\n\nIf used in the context of sanitization, double unescaping may render the sanitization ineffective. Even if it is not used in a security-critical context, it may still result in confusing or garbled output.\n\n\n## Recommendation\nUse a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation. For URI encoding, you can use the standard `encodeURIComponent` and `decodeURIComponent` functions.\n\nOtherwise, make sure to always escape the escape character first, and unescape it last.\n\n\n## Example\nThe following example shows a pair of hand-written HTML encoding and decoding functions:\n\n\n```javascript\nmodule.exports.encode = function(s) {\n return s.replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n};\n\nmodule.exports.decode = function(s) {\n return s.replace(/&/g, \"&\")\n .replace(/"/g, \"\\\"\")\n .replace(/'/g, \"'\");\n};\n\n```\nThe encoding function correctly handles ampersand before the other characters. For example, the string `me & \"you\"` is encoded as `me & "you"`, and the string `"` is encoded as `&quot;`.\n\nThe decoding function, however, incorrectly decodes `&` into `&` before handling the other characters. So while it correctly decodes the first example above, it decodes the second example (`&quot;`) to `\"` (a single double quote), which is not correct.\n\nInstead, the decoding function should decode the ampersand last:\n\n\n```javascript\nmodule.exports.encode = function(s) {\n return s.replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n};\n\nmodule.exports.decode = function(s) {\n return s.replace(/"/g, \"\\\"\")\n .replace(/'/g, \"'\")\n .replace(/&/g, \"&\");\n};\n\n```\n\n## References\n* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection).\n* npm: [html-entities](https://www.npmjs.com/package/html-entities) package.\n* npm: [js-string-escape](https://www.npmjs.com/package/js-string-escape) package.\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n" }, "properties" : { - "tags" : [ "security", "maintainability", "frameworks/angularjs", "external/cwe/cwe-116" ], - "description" : "Disabling strict contextual escaping (SCE) can cause security vulnerabilities.", - "id" : "js/angular/disabling-sce", + "tags" : [ "correctness", "security", "external/cwe/cwe-116", "external/cwe/cwe-020" ], + "description" : "When escaping special characters using a meta-character like backslash or\n ampersand, the meta-character has to be escaped first to avoid double-escaping,\n and conversely it has to be unescaped last to avoid double-unescaping.", + "id" : "js/double-escaping", "kind" : "problem", - "name" : "Disabling SCE", - "precision" : "very-high", + "name" : "Double escaping or unescaping", + "precision" : "high", "problem.severity" : "warning", "security-severity" : "7.8" } }, { - "id" : "js/loop-bound-injection", - "name" : "js/loop-bound-injection", + "id" : "js/incomplete-multi-character-sanitization", + "name" : "js/incomplete-multi-character-sanitization", "shortDescription" : { - "text" : "Loop bound injection" + "text" : "Incomplete multi-character sanitization" }, "fullDescription" : { - "text" : "Iterating over an object with a user-controlled .length property can cause indefinite looping." + "text" : "A sanitizer that removes a sequence of characters may reintroduce the dangerous sequence." }, "defaultConfiguration" : { "enabled" : true, "level" : "warning" }, "help" : { - "text" : "# Loop bound injection\nUsing the `.length` property of an untrusted object as a loop bound may cause indefinite looping since a malicious attacker can set the `.length` property to a very large number. For example, when a program that expects an array is passed a JSON object such as `{length: 1e100}`, the loop will be run for 10100 iterations. This may cause the program to hang or run out of memory, which can be used to mount a denial-of-service (DoS) attack.\n\n\n## Recommendation\nEither check that the object is indeed an array or limit the size of the `.length` property.\n\n\n## Example\nIn the example below, an HTTP request handler iterates over a user-controlled object `obj` using the `obj.length` property in order to copy the elements from `obj` to an array.\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\napp.post(\"/foo\", (req, res) => {\n var obj = req.body;\n\n var ret = [];\n\n // Potential DoS if obj.length is large.\n for (var i = 0; i < obj.length; i++) {\n ret.push(obj[i]);\n }\n});\n\n```\nThis is not secure since an attacker can control the value of `obj.length`, and thereby cause the loop to iterate indefinitely. Here the potential DoS is fixed by enforcing that the user-controlled object is an array.\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\napp.post(\"/foo\", (req, res) => {\n var obj = req.body;\n \n if (!(obj instanceof Array)) { // Prevents DoS.\n return [];\n }\n\n var ret = [];\n\n for (var i = 0; i < obj.length; i++) {\n ret.push(obj[i]);\n }\n});\n\n```\n\n## References\n* Common Weakness Enumeration: [CWE-834](https://cwe.mitre.org/data/definitions/834.html).\n* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html).\n", - "markdown" : "# Loop bound injection\nUsing the `.length` property of an untrusted object as a loop bound may cause indefinite looping since a malicious attacker can set the `.length` property to a very large number. For example, when a program that expects an array is passed a JSON object such as `{length: 1e100}`, the loop will be run for 10100 iterations. This may cause the program to hang or run out of memory, which can be used to mount a denial-of-service (DoS) attack.\n\n\n## Recommendation\nEither check that the object is indeed an array or limit the size of the `.length` property.\n\n\n## Example\nIn the example below, an HTTP request handler iterates over a user-controlled object `obj` using the `obj.length` property in order to copy the elements from `obj` to an array.\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\napp.post(\"/foo\", (req, res) => {\n var obj = req.body;\n\n var ret = [];\n\n // Potential DoS if obj.length is large.\n for (var i = 0; i < obj.length; i++) {\n ret.push(obj[i]);\n }\n});\n\n```\nThis is not secure since an attacker can control the value of `obj.length`, and thereby cause the loop to iterate indefinitely. Here the potential DoS is fixed by enforcing that the user-controlled object is an array.\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\napp.post(\"/foo\", (req, res) => {\n var obj = req.body;\n \n if (!(obj instanceof Array)) { // Prevents DoS.\n return [];\n }\n\n var ret = [];\n\n for (var i = 0; i < obj.length; i++) {\n ret.push(obj[i]);\n }\n});\n\n```\n\n## References\n* Common Weakness Enumeration: [CWE-834](https://cwe.mitre.org/data/definitions/834.html).\n* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html).\n" + "text" : "# Incomplete multi-character sanitization\nSanitizing untrusted input is a common technique for preventing injection attacks and other security vulnerabilities. Regular expressions are often used to perform this sanitization. However, when the regular expression matches multiple consecutive characters, replacing it just once can result in the unsafe text reappearing in the sanitized input.\n\nAttackers can exploit this issue by crafting inputs that, when sanitized with an ineffective regular expression, still contain malicious code or content. This can lead to code execution, data exposure, or other vulnerabilities.\n\n\n## Recommendation\nTo prevent this issue, it is highly recommended to use a well-tested sanitization library whenever possible. These libraries are more likely to handle corner cases and ensure effective sanitization.\n\nIf a library is not an option, you can consider alternative strategies to fix the issue. For example, applying the regular expression replacement repeatedly until no more replacements can be performed, or rewriting the regular expression to match single characters instead of the entire unsafe text.\n\n\n## Example\nConsider the following JavaScript code that aims to remove all HTML comment start and end tags:\n\n```javascript\n\nstr.replace(/`, and that HTML tag names can contain upper case characters.\n\n\n## References\n* Securitum: [The Curious Case of Copy & Paste](https://research.securitum.com/the-curious-case-of-copy-paste/).\n* stackoverflow.com: [You can't parse \\[X\\]HTML with regex](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags#answer-1732454).\n* HTML Standard: [Comment end bang state](https://html.spec.whatwg.org/multipage/parsing.html#comment-end-bang-state).\n* stackoverflow.com: [Why aren't browsers strict about HTML?](https://stackoverflow.com/questions/25559999/why-arent-browsers-strict-about-html).\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n* Common Weakness Enumeration: [CWE-80](https://cwe.mitre.org/data/definitions/80.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n* Common Weakness Enumeration: [CWE-184](https://cwe.mitre.org/data/definitions/184.html).\n* Common Weakness Enumeration: [CWE-185](https://cwe.mitre.org/data/definitions/185.html).\n* Common Weakness Enumeration: [CWE-186](https://cwe.mitre.org/data/definitions/186.html).\n", - "markdown" : "# Bad HTML filtering regexp\nIt is possible to match some single HTML tags using regular expressions (parsing general HTML using regular expressions is impossible). However, if the regular expression is not written well it might be possible to circumvent it, which can lead to cross-site scripting or other security issues.\n\nSome of these mistakes are caused by browsers having very forgiving HTML parsers, and will often render invalid HTML containing syntax errors. Regular expressions that attempt to match HTML should also recognize tags containing such syntax errors.\n\n\n## Recommendation\nUse a well-tested sanitization or parser library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation.\n\n\n## Example\nThe following example attempts to filters out all `` as script end tags, but also tags such as `` even though it is a parser error. This means that an attack string such as `` will not be filtered by the function, and `alert(1)` will be executed by a browser if the string is rendered as HTML.\n\nOther corner cases include that HTML comments can end with `--!>`, and that HTML tag names can contain upper case characters.\n\n\n## References\n* Securitum: [The Curious Case of Copy & Paste](https://research.securitum.com/the-curious-case-of-copy-paste/).\n* stackoverflow.com: [You can't parse \\[X\\]HTML with regex](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags#answer-1732454).\n* HTML Standard: [Comment end bang state](https://html.spec.whatwg.org/multipage/parsing.html#comment-end-bang-state).\n* stackoverflow.com: [Why aren't browsers strict about HTML?](https://stackoverflow.com/questions/25559999/why-arent-browsers-strict-about-html).\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n* Common Weakness Enumeration: [CWE-80](https://cwe.mitre.org/data/definitions/80.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n* Common Weakness Enumeration: [CWE-184](https://cwe.mitre.org/data/definitions/184.html).\n* Common Weakness Enumeration: [CWE-185](https://cwe.mitre.org/data/definitions/185.html).\n* Common Weakness Enumeration: [CWE-186](https://cwe.mitre.org/data/definitions/186.html).\n" + "text" : "# Creating biased random numbers from a cryptographically secure source\nGenerating secure random numbers can be an important part of creating a secure software system. This can be done using APIs that create cryptographically secure random numbers.\n\nHowever, using some mathematical operations on these cryptographically secure random numbers can create biased results, where some outcomes are more likely than others. Such biased results can make it easier for an attacker to guess the random numbers, and thereby break the security of the software system.\n\n\n## Recommendation\nBe very careful not to introduce bias when performing mathematical operations on cryptographically secure random numbers.\n\nIf possible, avoid performing mathematical operations on cryptographically secure random numbers at all, and use a preexisting library instead.\n\n\n## Example\nThe example below uses the modulo operator to create an array of 10 random digits using random bytes as the source for randomness.\n\n\n```javascript\nconst crypto = require('crypto');\n\nconst digits = [];\nfor (let i = 0; i < 10; i++) {\n digits.push(crypto.randomBytes(1)[0] % 10); // NOT OK\n}\n```\nThe random byte is a uniformly random value between 0 and 255, and thus the result from using the modulo operator is slightly more likely to be between 0 and 5 than between 6 and 9.\n\nThe issue has been fixed in the code below by using a library that correctly generates cryptographically secure random values.\n\n\n```javascript\nconst cryptoRandomString = require('crypto-random-string');\n\nconst digits = cryptoRandomString({length: 10, type: 'numeric'});\n```\nAlternatively, the issue can be fixed by fixing the math in the original code. In the code below the random byte is discarded if the value is greater than or equal to 250. Thus the modulo operator is used on a uniformly random number between 0 and 249, which results in a uniformly random digit between 0 and 9.\n\n\n```javascript\nconst crypto = require('crypto');\n\nconst digits = [];\nwhile (digits.length < 10) {\n const byte = crypto.randomBytes(1)[0];\n if (byte >= 250) {\n continue;\n }\n digits.push(byte % 10); // OK\n}\n```\n\n## References\n* Stack Overflow: [Understanding “randomness”](https://stackoverflow.com/questions/3956478/understanding-randomness).\n* OWASP: [Insecure Randomness](https://owasp.org/www-community/vulnerabilities/Insecure_Randomness).\n* OWASP: [Rule - Use strong approved cryptographic algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption).\n* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html).\n", + "markdown" : "# Creating biased random numbers from a cryptographically secure source\nGenerating secure random numbers can be an important part of creating a secure software system. This can be done using APIs that create cryptographically secure random numbers.\n\nHowever, using some mathematical operations on these cryptographically secure random numbers can create biased results, where some outcomes are more likely than others. Such biased results can make it easier for an attacker to guess the random numbers, and thereby break the security of the software system.\n\n\n## Recommendation\nBe very careful not to introduce bias when performing mathematical operations on cryptographically secure random numbers.\n\nIf possible, avoid performing mathematical operations on cryptographically secure random numbers at all, and use a preexisting library instead.\n\n\n## Example\nThe example below uses the modulo operator to create an array of 10 random digits using random bytes as the source for randomness.\n\n\n```javascript\nconst crypto = require('crypto');\n\nconst digits = [];\nfor (let i = 0; i < 10; i++) {\n digits.push(crypto.randomBytes(1)[0] % 10); // NOT OK\n}\n```\nThe random byte is a uniformly random value between 0 and 255, and thus the result from using the modulo operator is slightly more likely to be between 0 and 5 than between 6 and 9.\n\nThe issue has been fixed in the code below by using a library that correctly generates cryptographically secure random values.\n\n\n```javascript\nconst cryptoRandomString = require('crypto-random-string');\n\nconst digits = cryptoRandomString({length: 10, type: 'numeric'});\n```\nAlternatively, the issue can be fixed by fixing the math in the original code. In the code below the random byte is discarded if the value is greater than or equal to 250. Thus the modulo operator is used on a uniformly random number between 0 and 249, which results in a uniformly random digit between 0 and 9.\n\n\n```javascript\nconst crypto = require('crypto');\n\nconst digits = [];\nwhile (digits.length < 10) {\n const byte = crypto.randomBytes(1)[0];\n if (byte >= 250) {\n continue;\n }\n digits.push(byte % 10); // OK\n}\n```\n\n## References\n* Stack Overflow: [Understanding “randomness”](https://stackoverflow.com/questions/3956478/understanding-randomness).\n* OWASP: [Insecure Randomness](https://owasp.org/www-community/vulnerabilities/Insecure_Randomness).\n* OWASP: [Rule - Use strong approved cryptographic algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption).\n* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html).\n" }, "properties" : { - "tags" : [ "correctness", "security", "external/cwe/cwe-020", "external/cwe/cwe-080", "external/cwe/cwe-116", "external/cwe/cwe-184", "external/cwe/cwe-185", "external/cwe/cwe-186" ], - "description" : "Matching HTML tags using regular expressions is hard to do right, and can easily lead to security issues.", - "id" : "js/bad-tag-filter", + "tags" : [ "security", "external/cwe/cwe-327" ], + "description" : "Some mathematical operations on random numbers can cause bias in\n the results and compromise security.", + "id" : "js/biased-cryptographic-random", "kind" : "problem", - "name" : "Bad HTML filtering regexp", + "name" : "Creating biased random numbers from a cryptographically secure source", "precision" : "high", "problem.severity" : "warning", - "security-severity" : "7.8" + "security-severity" : "7.5" } }, { - "id" : "js/incomplete-sanitization", - "name" : "js/incomplete-sanitization", + "id" : "js/bad-code-sanitization", + "name" : "js/bad-code-sanitization", "shortDescription" : { - "text" : "Incomplete string escaping or encoding" + "text" : "Improper code sanitization" }, "fullDescription" : { - "text" : "A string transformer that does not replace or escape all occurrences of a meta-character may be ineffective." + "text" : "Escaping code as HTML does not provide protection against code injection." }, "defaultConfiguration" : { "enabled" : true, - "level" : "warning" + "level" : "error" }, "help" : { - "text" : "# Incomplete string escaping or encoding\nSanitizing untrusted input is a common technique for preventing injection attacks such as SQL injection or cross-site scripting. Usually, this is done by escaping meta-characters such as quotes in a domain-specific way so that they are treated as normal characters.\n\nHowever, directly using the string `replace` method to perform escaping is notoriously error-prone. Common mistakes include only replacing the first occurrence of a meta-character, or backslash-escaping various meta-characters but not the backslash itself.\n\nIn the former case, later meta-characters are left undisturbed and can be used to subvert the sanitization. In the latter case, preceding a meta-character with a backslash leads to the backslash being escaped, but the meta-character appearing un-escaped, which again makes the sanitization ineffective.\n\nEven if the escaped string is not used in a security-critical context, incomplete escaping may still have undesirable effects, such as badly rendered or confusing output.\n\n\n## Recommendation\nUse a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation.\n\nAn even safer alternative is to design the application so that sanitization is not needed, for instance by using prepared statements for SQL queries.\n\nOtherwise, make sure to use a regular expression with the `g` flag to ensure that all occurrences are replaced, and remember to escape backslashes if applicable.\n\n\n## Example\nFor example, assume that we want to embed a user-controlled string `accountNumber` into a SQL query as part of a string literal. To avoid SQL injection, we need to ensure that the string does not contain un-escaped single-quote characters. The following function attempts to ensure this by doubling single quotes, and thereby escaping them:\n\n\n```javascript\nfunction escapeQuotes(s) {\n return s.replace(\"'\", \"''\");\n}\n\n```\nAs written, this sanitizer is ineffective: if the first argument to `replace` is a string literal (as in this case), only the *first* occurrence of that string is replaced.\n\nAs mentioned above, the function `escapeQuotes` should be replaced with a purpose-built sanitization library, such as the npm module `sqlstring`. Many other sanitization libraries are available from npm and other sources.\n\nIf this is not an option, `escapeQuotes` should be rewritten to use a regular expression with the `g` (\"global\") flag instead:\n\n\n```javascript\nfunction escapeQuotes(s) {\n return s.replace(/'/g, \"''\");\n}\n\n```\nNote that it is very important to include the global flag: `s.replace(/'/, \"''\")` *without* the global flag is equivalent to the first example above and only replaces the first quote.\n\n\n## References\n* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection).\n* npm: [sqlstring](https://www.npmjs.com/package/sqlstring) package.\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n* Common Weakness Enumeration: [CWE-80](https://cwe.mitre.org/data/definitions/80.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n", - "markdown" : "# Incomplete string escaping or encoding\nSanitizing untrusted input is a common technique for preventing injection attacks such as SQL injection or cross-site scripting. Usually, this is done by escaping meta-characters such as quotes in a domain-specific way so that they are treated as normal characters.\n\nHowever, directly using the string `replace` method to perform escaping is notoriously error-prone. Common mistakes include only replacing the first occurrence of a meta-character, or backslash-escaping various meta-characters but not the backslash itself.\n\nIn the former case, later meta-characters are left undisturbed and can be used to subvert the sanitization. In the latter case, preceding a meta-character with a backslash leads to the backslash being escaped, but the meta-character appearing un-escaped, which again makes the sanitization ineffective.\n\nEven if the escaped string is not used in a security-critical context, incomplete escaping may still have undesirable effects, such as badly rendered or confusing output.\n\n\n## Recommendation\nUse a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation.\n\nAn even safer alternative is to design the application so that sanitization is not needed, for instance by using prepared statements for SQL queries.\n\nOtherwise, make sure to use a regular expression with the `g` flag to ensure that all occurrences are replaced, and remember to escape backslashes if applicable.\n\n\n## Example\nFor example, assume that we want to embed a user-controlled string `accountNumber` into a SQL query as part of a string literal. To avoid SQL injection, we need to ensure that the string does not contain un-escaped single-quote characters. The following function attempts to ensure this by doubling single quotes, and thereby escaping them:\n\n\n```javascript\nfunction escapeQuotes(s) {\n return s.replace(\"'\", \"''\");\n}\n\n```\nAs written, this sanitizer is ineffective: if the first argument to `replace` is a string literal (as in this case), only the *first* occurrence of that string is replaced.\n\nAs mentioned above, the function `escapeQuotes` should be replaced with a purpose-built sanitization library, such as the npm module `sqlstring`. Many other sanitization libraries are available from npm and other sources.\n\nIf this is not an option, `escapeQuotes` should be rewritten to use a regular expression with the `g` (\"global\") flag instead:\n\n\n```javascript\nfunction escapeQuotes(s) {\n return s.replace(/'/g, \"''\");\n}\n\n```\nNote that it is very important to include the global flag: `s.replace(/'/, \"''\")` *without* the global flag is equivalent to the first example above and only replaces the first quote.\n\n\n## References\n* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection).\n* npm: [sqlstring](https://www.npmjs.com/package/sqlstring) package.\n* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n* Common Weakness Enumeration: [CWE-80](https://cwe.mitre.org/data/definitions/80.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n" + "text" : "# Improper code sanitization\nUsing string concatenation to construct JavaScript code can be error-prone, or in the worst case, enable code injection if an input is constructed by an attacker.\n\n\n## Recommendation\nIf using `JSON.stringify` or an HTML sanitizer to sanitize a string inserted into JavaScript code, then make sure to perform additional sanitization or remove potentially dangerous characters.\n\n\n## Example\nThe example below constructs a function that assigns the number 42 to the property `key` on an object `obj`. However, if `key` contains ``, then the generated code will break out of a `` if inserted into a `` tag.\n\n\n```javascript\nfunction createObjectWrite() {\n const assignment = `obj[${JSON.stringify(key)}]=42`;\n return `(function(){${assignment}})` // NOT OK\n}\n```\nThe issue has been fixed by escaping potentially dangerous characters, as shown below.\n\n\n```javascript\nconst charMap = {\n '<': '\\\\u003C',\n '>' : '\\\\u003E',\n '/': '\\\\u002F',\n '\\\\': '\\\\\\\\',\n '\\b': '\\\\b',\n '\\f': '\\\\f',\n '\\n': '\\\\n',\n '\\r': '\\\\r',\n '\\t': '\\\\t',\n '\\0': '\\\\0',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029'\n};\n\nfunction escapeUnsafeChars(str) {\n return str.replace(/[<>\\b\\f\\n\\r\\t\\0\\u2028\\u2029]/g, x => charMap[x])\n}\n\nfunction createObjectWrite() {\n const assignment = `obj[${escapeUnsafeChars(JSON.stringify(key))}]=42`;\n return `(function(){${assignment}})` // OK\n}\n```\n\n## References\n* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection).\n* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html).\n* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n", + "markdown" : "# Improper code sanitization\nUsing string concatenation to construct JavaScript code can be error-prone, or in the worst case, enable code injection if an input is constructed by an attacker.\n\n\n## Recommendation\nIf using `JSON.stringify` or an HTML sanitizer to sanitize a string inserted into JavaScript code, then make sure to perform additional sanitization or remove potentially dangerous characters.\n\n\n## Example\nThe example below constructs a function that assigns the number 42 to the property `key` on an object `obj`. However, if `key` contains ``, then the generated code will break out of a `` if inserted into a `` tag.\n\n\n```javascript\nfunction createObjectWrite() {\n const assignment = `obj[${JSON.stringify(key)}]=42`;\n return `(function(){${assignment}})` // NOT OK\n}\n```\nThe issue has been fixed by escaping potentially dangerous characters, as shown below.\n\n\n```javascript\nconst charMap = {\n '<': '\\\\u003C',\n '>' : '\\\\u003E',\n '/': '\\\\u002F',\n '\\\\': '\\\\\\\\',\n '\\b': '\\\\b',\n '\\f': '\\\\f',\n '\\n': '\\\\n',\n '\\r': '\\\\r',\n '\\t': '\\\\t',\n '\\0': '\\\\0',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029'\n};\n\nfunction escapeUnsafeChars(str) {\n return str.replace(/[<>\\b\\f\\n\\r\\t\\0\\u2028\\u2029]/g, x => charMap[x])\n}\n\nfunction createObjectWrite() {\n const assignment = `obj[${escapeUnsafeChars(JSON.stringify(key))}]=42`;\n return `(function(){${assignment}})` // OK\n}\n```\n\n## References\n* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection).\n* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html).\n* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n" }, "properties" : { - "tags" : [ "correctness", "security", "external/cwe/cwe-020", "external/cwe/cwe-080", "external/cwe/cwe-116" ], - "description" : "A string transformer that does not replace or escape all occurrences of a\n meta-character may be ineffective.", - "id" : "js/incomplete-sanitization", - "kind" : "problem", - "name" : "Incomplete string escaping or encoding", + "tags" : [ "security", "external/cwe/cwe-094", "external/cwe/cwe-079", "external/cwe/cwe-116" ], + "description" : "Escaping code as HTML does not provide protection against code injection.", + "id" : "js/bad-code-sanitization", + "kind" : "path-problem", + "name" : "Improper code sanitization", "precision" : "high", - "problem.severity" : "warning", - "security-severity" : "7.8" + "problem.severity" : "error", + "security-severity" : "6.1" } }, { - "id" : "js/unsafe-html-expansion", - "name" : "js/unsafe-html-expansion", + "id" : "js/actions/command-injection", + "name" : "js/actions/command-injection", "shortDescription" : { - "text" : "Unsafe expansion of self-closing HTML tag" + "text" : "Expression injection in Actions" }, "fullDescription" : { - "text" : "Using regular expressions to expand self-closing HTML tags may lead to cross-site scripting vulnerabilities." + "text" : "Using user-controlled GitHub Actions contexts like `run:` or `script:` may allow a malicious user to inject code into the GitHub action." }, "defaultConfiguration" : { "enabled" : true, "level" : "warning" }, "help" : { - "text" : "# Unsafe expansion of self-closing HTML tag\nSanitizing untrusted input for HTML meta-characters is a common technique for preventing cross-site scripting attacks. But even a sanitized input can be dangerous to use if it is modified further before a browser treats it as HTML. A seemingly innocent transformation that expands a self-closing HTML tag from `
` to `
` may in fact cause cross-site scripting vulnerabilities.\n\n\n## Recommendation\nUse a well-tested sanitization library if at all possible, and avoid modifying sanitized values further before treating them as HTML.\n\nAn even safer alternative is to design the application so that sanitization is not needed, for instance by using HTML templates that are explicit about the values they treat as HTML.\n\n\n## Example\nThe following function transforms a self-closing HTML tag to a pair of open/close tags. It does so for all non-`img` and non-`area` tags, by using a regular expression with two capture groups. The first capture group corresponds to the name of the tag, and the second capture group to the content of the tag.\n\n\n```javascript\nfunction expandSelfClosingTags(html) {\n\tvar rxhtmlTag = /<(?!img|area)(([a-z][^\\w\\/>]*)[^>]*)\\/>/gi;\n\treturn html.replace(rxhtmlTag, \"<$1>\"); // BAD\n}\n\n```\nWhile it is generally known regular expressions are ill-suited for parsing HTML, variants of this particular transformation pattern have long been considered safe.\n\nHowever, the function is not safe. As an example, consider the following string:\n\n\n```html\n
\n\"/>\n\n```\nWhen the above function transforms the string, it becomes a string that results in an alert when a browser treats it as HTML.\n\n\n```html\n
\n\"/>\n\n```\n\n## References\n* jQuery: [Security fixes in jQuery 3.5.0](https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/)\n* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html).\n* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).\n* OWASP [Types of Cross-Site](https://owasp.org/www-community/Types_of_Cross-Site_Scripting).\n* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting).\n* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n", - "markdown" : "# Unsafe expansion of self-closing HTML tag\nSanitizing untrusted input for HTML meta-characters is a common technique for preventing cross-site scripting attacks. But even a sanitized input can be dangerous to use if it is modified further before a browser treats it as HTML. A seemingly innocent transformation that expands a self-closing HTML tag from `
` to `
` may in fact cause cross-site scripting vulnerabilities.\n\n\n## Recommendation\nUse a well-tested sanitization library if at all possible, and avoid modifying sanitized values further before treating them as HTML.\n\nAn even safer alternative is to design the application so that sanitization is not needed, for instance by using HTML templates that are explicit about the values they treat as HTML.\n\n\n## Example\nThe following function transforms a self-closing HTML tag to a pair of open/close tags. It does so for all non-`img` and non-`area` tags, by using a regular expression with two capture groups. The first capture group corresponds to the name of the tag, and the second capture group to the content of the tag.\n\n\n```javascript\nfunction expandSelfClosingTags(html) {\n\tvar rxhtmlTag = /<(?!img|area)(([a-z][^\\w\\/>]*)[^>]*)\\/>/gi;\n\treturn html.replace(rxhtmlTag, \"<$1>\"); // BAD\n}\n\n```\nWhile it is generally known regular expressions are ill-suited for parsing HTML, variants of this particular transformation pattern have long been considered safe.\n\nHowever, the function is not safe. As an example, consider the following string:\n\n\n```html\n
\n\"/>\n\n```\nWhen the above function transforms the string, it becomes a string that results in an alert when a browser treats it as HTML.\n\n\n```html\n
\n\"/>\n\n```\n\n## References\n* jQuery: [Security fixes in jQuery 3.5.0](https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/)\n* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html).\n* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).\n* OWASP [Types of Cross-Site](https://owasp.org/www-community/Types_of_Cross-Site_Scripting).\n* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting).\n* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html).\n* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html).\n" + "text" : "# Expression injection in Actions\nUsing user-controlled input in GitHub Actions may lead to code injection in contexts like *run:* or *script:*.\n\nCode injection in GitHub Actions may allow an attacker to exfiltrate any secrets used in the workflow and the temporary GitHub repository authorization token. The token might have write access to the repository, allowing an attacker to use the token to make changes to the repository.\n\n\n## Recommendation\nThe best practice to avoid code injection vulnerabilities in GitHub workflows is to set the untrusted input value of the expression to an intermediate environment variable and then use the environment variable using the native syntax of the shell/script interpreter (that is, not *${{ env.VAR }}*).\n\nIt is also recommended to limit the permissions of any tokens used by a workflow such as the GITHUB_TOKEN.\n\n\n## Example\nThe following example lets a user inject an arbitrary shell command:\n\n\n```yaml\non: issue_comment\n\njobs:\n echo-body:\n runs-on: ubuntu-latest\n steps:\n - run: |\n echo '${{ github.event.comment.body }}'\n```\nThe following example uses an environment variable, but **still allows the injection** because of the use of expression syntax:\n\n\n```yaml\non: issue_comment\n\njobs:\n echo-body:\n runs-on: ubuntu-latest\n steps:\n - env:\n BODY: ${{ github.event.issue.body }}\n run: |\n echo '${{ env.BODY }}'\n```\nThe following example uses shell syntax to read the environment variable and will prevent the attack:\n\n\n```yaml\non: issue_comment\n\njobs:\n echo-body:\n runs-on: ubuntu-latest\n steps:\n - env:\n BODY: ${{ github.event.issue.body }}\n run: |\n echo \"$BODY\"\n\n```\n\n## References\n* GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure: Untrusted input](https://securitylab.github.com/research/github-actions-untrusted-input).\n* GitHub Docs: [Security hardening for GitHub Actions](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions).\n* GitHub Docs: [Permissions for the GITHUB_TOKEN](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token).\n* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html).\n", + "markdown" : "# Expression injection in Actions\nUsing user-controlled input in GitHub Actions may lead to code injection in contexts like *run:* or *script:*.\n\nCode injection in GitHub Actions may allow an attacker to exfiltrate any secrets used in the workflow and the temporary GitHub repository authorization token. The token might have write access to the repository, allowing an attacker to use the token to make changes to the repository.\n\n\n## Recommendation\nThe best practice to avoid code injection vulnerabilities in GitHub workflows is to set the untrusted input value of the expression to an intermediate environment variable and then use the environment variable using the native syntax of the shell/script interpreter (that is, not *${{ env.VAR }}*).\n\nIt is also recommended to limit the permissions of any tokens used by a workflow such as the GITHUB_TOKEN.\n\n\n## Example\nThe following example lets a user inject an arbitrary shell command:\n\n\n```yaml\non: issue_comment\n\njobs:\n echo-body:\n runs-on: ubuntu-latest\n steps:\n - run: |\n echo '${{ github.event.comment.body }}'\n```\nThe following example uses an environment variable, but **still allows the injection** because of the use of expression syntax:\n\n\n```yaml\non: issue_comment\n\njobs:\n echo-body:\n runs-on: ubuntu-latest\n steps:\n - env:\n BODY: ${{ github.event.issue.body }}\n run: |\n echo '${{ env.BODY }}'\n```\nThe following example uses shell syntax to read the environment variable and will prevent the attack:\n\n\n```yaml\non: issue_comment\n\njobs:\n echo-body:\n runs-on: ubuntu-latest\n steps:\n - env:\n BODY: ${{ github.event.issue.body }}\n run: |\n echo \"$BODY\"\n\n```\n\n## References\n* GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure: Untrusted input](https://securitylab.github.com/research/github-actions-untrusted-input).\n* GitHub Docs: [Security hardening for GitHub Actions](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions).\n* GitHub Docs: [Permissions for the GITHUB_TOKEN](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token).\n* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html).\n" }, "properties" : { - "tags" : [ "correctness", "security", "external/cwe/cwe-079", "external/cwe/cwe-116" ], - "description" : "Using regular expressions to expand self-closing HTML\n tags may lead to cross-site scripting vulnerabilities.", - "id" : "js/unsafe-html-expansion", + "tags" : [ "actions", "security", "external/cwe/cwe-094" ], + "description" : "Using user-controlled GitHub Actions contexts like `run:` or `script:` may allow a malicious\n user to inject code into the GitHub action.", + "id" : "js/actions/command-injection", "kind" : "problem", - "name" : "Unsafe expansion of self-closing HTML tag", - "precision" : "very-high", + "name" : "Expression injection in Actions", + "precision" : "high", "problem.severity" : "warning", - "security-severity" : "6.1" + "security-severity" : "9.3" } }, { - "id" : "js/incomplete-multi-character-sanitization", - "name" : "js/incomplete-multi-character-sanitization", + "id" : "js/unsafe-dynamic-method-access", + "name" : "js/unsafe-dynamic-method-access", "shortDescription" : { - "text" : "Incomplete multi-character sanitization" + "text" : "Unsafe dynamic method access" }, "fullDescription" : { - "text" : "A sanitizer that removes a sequence of characters may reintroduce the dangerous sequence." + "text" : "Invoking user-controlled methods on certain objects can lead to remote code execution." }, "defaultConfiguration" : { "enabled" : true, - "level" : "warning" + "level" : "error" }, "help" : { - "text" : "# Incomplete multi-character sanitization\nSanitizing untrusted input is a common technique for preventing injection attacks and other security vulnerabilities. Regular expressions are often used to perform this sanitization. However, when the regular expression matches multiple consecutive characters, replacing it just once can result in the unsafe text reappearing in the sanitized input.\n\nAttackers can exploit this issue by crafting inputs that, when sanitized with an ineffective regular expression, still contain malicious code or content. This can lead to code execution, data exposure, or other vulnerabilities.\n\n\n## Recommendation\nTo prevent this issue, it is highly recommended to use a well-tested sanitization library whenever possible. These libraries are more likely to handle corner cases and ensure effective sanitization.\n\nIf a library is not an option, you can consider alternative strategies to fix the issue. For example, applying the regular expression replacement repeatedly until no more replacements can be performed, or rewriting the regular expression to match single characters instead of the entire unsafe text.\n\n\n## Example\nConsider the following JavaScript code that aims to remove all HTML comment start and end tags:\n\n```javascript\n\nstr.replace(/