diff --git a/.github/workflows/code_scanning.yml b/.github/workflows/code_scanning.yml
index 0d229fd3d..b4651d90f 100644
--- a/.github/workflows/code_scanning.yml
+++ b/.github/workflows/code_scanning.yml
@@ -35,14 +35,49 @@ jobs:
mv $dir .github/codeql/extensions/$dir
done
-
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: javascript
config-file: ./.github/codeql/codeql-config.yaml
debug: true
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ id: analyze
+ uses: github/codeql-action/analyze@v3
+
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ 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
+ run: |
+ pip install sarif-tools
+ sarif --version
+ sarif diff ${{ steps.analyze.outputs.sarif-output }} .github/workflows/javascript.sarif.expected -o sarif-diff.json
+ ! grep -q "[1-9]" sarif-diff.json
+
+ - name: Upload sarif change
+ if: steps.validate.outcome != 'success'
+ uses: actions/upload-artifact@v4
+ with:
+ name: sarif
+ 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
new file mode 100644
index 000000000..4993ec9b7
--- /dev/null
+++ b/.github/workflows/javascript.sarif.expected
@@ -0,0 +1,21462 @@
+{
+ "$schema" : "https://json.schemastore.org/sarif-2.1.0.json",
+ "version" : "2.1.0",
+ "runs" : [ {
+ "tool" : {
+ "driver" : {
+ "name" : "CodeQL",
+ "organization" : "GitHub",
+ "semanticVersion" : "2.16.1",
+ "notifications" : [ {
+ "id" : "cli/expected-extracted-files/javascript",
+ "name" : "cli/expected-extracted-files/javascript",
+ "shortDescription" : {
+ "text" : "Expected extracted files"
+ },
+ "fullDescription" : {
+ "text" : "Files appearing in the source archive that are expected to be extracted."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true
+ },
+ "properties" : {
+ "tags" : [ "expected-extracted-files", "telemetry" ],
+ "languageDisplayName" : "JavaScript"
+ }
+ }, {
+ "id" : "cli/expected-extracted-files/python",
+ "name" : "cli/expected-extracted-files/python",
+ "shortDescription" : {
+ "text" : "Expected extracted files"
+ },
+ "fullDescription" : {
+ "text" : "Files appearing in the source archive that are expected to be extracted."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true
+ },
+ "properties" : {
+ "tags" : [ "expected-extracted-files", "telemetry" ],
+ "languageDisplayName" : "Python"
+ }
+ } ],
+ "rules" : [ ]
+ },
+ "extensions" : [ {
+ "name" : "advanced-security/javascript-sap-ui5-queries",
+ "semanticVersion" : "0.5.0+d4326cab70648ae61cc6f8988b7d2cb72ceb5e13",
+ "rules" : [ {
+ "id" : "js/ui5-path-injection",
+ "name" : "js/ui5-path-injection",
+ "shortDescription" : {
+ "text" : "UI5 Path Injection"
+ },
+ "fullDescription" : {
+ "text" : "Constructing path from an uncontrolled remote source to be passed to a filesystem API allows for manipulation of the local filesystem."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Client-side path injection\n\nUI5 applications that access files using a dynamically configured path are vulnerable to injection attacks that allow an attacker to manipulate the file location.\n\n## Recommendation\n\n### Make path argument independent of the user input\n\nIf possible, do not parameterize the path on a user input. Either hardcode the path string in the source, or use only strings that are created within the application.\n\n### Keep an allow-list of safe paths\n\nKeep a strict allow-list of safe paths to load from or send requests to. Before loading a script from a location outside the application or making an API request to a location, check if the path is contained in the list of safe paths. Also, make sure that the allow-list is kept up to date.\n\n### Check the script into the repository or use package managers\n\nSince the URL of the script may be pointing to a web server vulnerable to being hijacked, it may be a good idea to check a stable version of the script into the repository to increase the degree of control. If not possible, use a trusted package manager such as `npm`.\n\n## Example\n\n### Including scripts from an untrusted domain\n\n``` javascript\nsap.ui.require([\n \"sap/ui/dom/includeScript\"\n ],\n function(includeScript) {\n includeScript(\"http://some.vulnerable.domain/some-script.js\");\n }\n);\n```\n\nIf the vulnerable domain is outside the organization and controlled by an untrusted third party, this may result in arbitrary code execution in the user's browser.\n\n### Using user input as a name of a file to be saved\n\nSuppose a controller is configured to receive a response from a server as follows.\n\n``` javascript\nsap.ui.define([\n \"sap/ui/core/mvc/Controller\",\n \"sap/ui/core/util/File\"\n ],\n function(Controller, File) {\n return Controller.extend(\"vulnerable.controller.app\", {\n onInit: function() {\n let oDataV2Model = this.getOwnerComponent().getModel(\"some-ODatav2-model\");\n this.getView().setModel(oDataV2Model);\n },\n \n onSomeEvent: function() {\n let remoteResponse = this.getView().getModel().getProperty(\"someProperty\");\n File.save(\"some-content\", remoteResponse, \"txt\", \"text/plain\", \"utf-8\");\n }\n });\n });\n```\n\nEven if the server which updates the OData V2 model is in a trusted domain such as within the organization, the server may still contain tainted information if the UI5 application in question is vulnerable to other security attacks, say XSS. This may allow an attacker to save a file in the victim's local filesystem.\n\n## References\n\n- [CWE-829](https://cwe.mitre.org/data/definitions/829.html): Inclusion of Functionality from Untrusted Control Sphere\n- [CWE-073](https://cwe.mitre.org/data/definitions/73.html): External Control of File Name or Path\n- [API Documentation of `sap.ui.core.util.File`](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.util.File%23methods/sap.ui.core.util.File.save)\n- [API Documentation of `sap.ui.dom.includeScript`](https://sapui5.hana.ondemand.com/sdk/#/api/module:sap/ui/dom/includeScript) and [`sap.ui.dom.includeStyleSheet`](https://sapui5.hana.ondemand.com/sdk/#/api/module:sap/ui/dom/includeStylesheet)\n- [API Documentation of `jQuery.sap.includeScript`](https://sapui5.hana.ondemand.com/sdk/#/api/module:sap/ui/dom/includeScript) and [`jQuery.sap.includeStyleSheet`](https://sapui5.hana.ondemand.com/sdk/#/api/module:sap/ui/dom/includeScript)\n",
+ "markdown" : "# Client-side path injection\n\nUI5 applications that access files using a dynamically configured path are vulnerable to injection attacks that allow an attacker to manipulate the file location.\n\n## Recommendation\n\n### Make path argument independent of the user input\n\nIf possible, do not parameterize the path on a user input. Either hardcode the path string in the source, or use only strings that are created within the application.\n\n### Keep an allow-list of safe paths\n\nKeep a strict allow-list of safe paths to load from or send requests to. Before loading a script from a location outside the application or making an API request to a location, check if the path is contained in the list of safe paths. Also, make sure that the allow-list is kept up to date.\n\n### Check the script into the repository or use package managers\n\nSince the URL of the script may be pointing to a web server vulnerable to being hijacked, it may be a good idea to check a stable version of the script into the repository to increase the degree of control. If not possible, use a trusted package manager such as `npm`.\n\n## Example\n\n### Including scripts from an untrusted domain\n\n``` javascript\nsap.ui.require([\n \"sap/ui/dom/includeScript\"\n ],\n function(includeScript) {\n includeScript(\"http://some.vulnerable.domain/some-script.js\");\n }\n);\n```\n\nIf the vulnerable domain is outside the organization and controlled by an untrusted third party, this may result in arbitrary code execution in the user's browser.\n\n### Using user input as a name of a file to be saved\n\nSuppose a controller is configured to receive a response from a server as follows.\n\n``` javascript\nsap.ui.define([\n \"sap/ui/core/mvc/Controller\",\n \"sap/ui/core/util/File\"\n ],\n function(Controller, File) {\n return Controller.extend(\"vulnerable.controller.app\", {\n onInit: function() {\n let oDataV2Model = this.getOwnerComponent().getModel(\"some-ODatav2-model\");\n this.getView().setModel(oDataV2Model);\n },\n \n onSomeEvent: function() {\n let remoteResponse = this.getView().getModel().getProperty(\"someProperty\");\n File.save(\"some-content\", remoteResponse, \"txt\", \"text/plain\", \"utf-8\");\n }\n });\n });\n```\n\nEven if the server which updates the OData V2 model is in a trusted domain such as within the organization, the server may still contain tainted information if the UI5 application in question is vulnerable to other security attacks, say XSS. This may allow an attacker to save a file in the victim's local filesystem.\n\n## References\n\n- [CWE-829](https://cwe.mitre.org/data/definitions/829.html): Inclusion of Functionality from Untrusted Control Sphere\n- [CWE-073](https://cwe.mitre.org/data/definitions/73.html): External Control of File Name or Path\n- [API Documentation of `sap.ui.core.util.File`](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.util.File%23methods/sap.ui.core.util.File.save)\n- [API Documentation of `sap.ui.dom.includeScript`](https://sapui5.hana.ondemand.com/sdk/#/api/module:sap/ui/dom/includeScript) and [`sap.ui.dom.includeStyleSheet`](https://sapui5.hana.ondemand.com/sdk/#/api/module:sap/ui/dom/includeStylesheet)\n- [API Documentation of `jQuery.sap.includeScript`](https://sapui5.hana.ondemand.com/sdk/#/api/module:sap/ui/dom/includeScript) and [`jQuery.sap.includeStyleSheet`](https://sapui5.hana.ondemand.com/sdk/#/api/module:sap/ui/dom/includeScript)\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-022", "external/cwe/cwe-035" ],
+ "description" : "Constructing path from an uncontrolled remote source to be passed\n to a filesystem API allows for manipulation of the local filesystem.",
+ "id" : "js/ui5-path-injection",
+ "kind" : "path-problem",
+ "name" : "UI5 Path Injection",
+ "precision" : "medium",
+ "problem.severity" : "error",
+ "security-severity" : "7.8"
+ }
+ }, {
+ "id" : "js/ui5-formula-injection",
+ "name" : "js/ui5-formula-injection",
+ "shortDescription" : {
+ "text" : "UI5 Formula Injection"
+ },
+ "fullDescription" : {
+ "text" : "Saving data from an uncontrolled remote source using filesystem or local storage leads to disclosure of sensitive information or forgery of entry."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Formula injection\n\nUI5 applications that save local data, fetched from an uncontrolled remote source, into a CSV file format using generic APIs such as [`sap.ui.core.util.File.save`](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.util.File%23methods/sap.ui.core.util.File.save) are vulnerable to formula injection, or CSV injection.\n\n## Recommendation\n\n### Escape the leading special characters\n\nCSV cells containing a leading special characters such as the equal sign (`=`) may be interpreted as spreadsheet formulas. Therefore, these prefixes should be escaped with surrounding single quotes in order to have them interpreted as literal strings.\n\n### Use a dedicated API function\n\nAs in other injection attacks, it is not recommended to use string concatenation to assemble data passed into a generic file-saving function, even if sanitizers are to be used. Instead, a dedicated library function should be used. For example, if the target being exported is a [sap.m.Table](https://sapui5.hana.ondemand.com/sdk/#/api/sap.m.Table) and the resulting file is intended to be opened using a spreadsheet program, then using one of the API functions provided by [`sap.ui.export.Spreadsheet`](https://sapui5.hana.ondemand.com/#/entity/sap.ui.export.Spreadsheet) is the preferred method of achieving the same exporting functionality.\n\n## Example\n\nThe following controller is exporting a CSV file obtained from an event parameter by surrounding it in a pair of semicolons (`;`) as CSV separators.\n\n``` javascript\nsap.ui.define([\n \"sap/ui/core/Controller\",\n \"sap/ui/core/util/File\"\n ], function(Controller, File) {\n return Controller.extend(\"vulnerable.controller.app\", {\n onSomeEvent: function(oEvent) {\n let response = oEvent.getProperty(\"someProperty\").someField;\n let csvRow = \";\" + response + \";\";\n File.save(csvRow, \"someFile\", \"csv\", \"text/csv\", \"utf-8\");\n }\n });\n });\n```\n\n## References\n\n- OWASP: [CSV Injection](https://owasp.org/www-community/attacks/CSV_Injection)\n- [CWE-1236](https://cwe.mitre.org/data/definitions/1236.html): Improper Neutralization of Formula Elements in a CSV File\n- API Documentation: [`sap.ui.export.Spreadsheet`](https://sapui5.hana.ondemand.com/#/entity/sap.ui.export.Spreadsheet)\n- API Documentation: [`sap.ui.core.util.File.save`](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.util.File%23methods/sap.ui.core.util.File.save)\n",
+ "markdown" : "# Formula injection\n\nUI5 applications that save local data, fetched from an uncontrolled remote source, into a CSV file format using generic APIs such as [`sap.ui.core.util.File.save`](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.util.File%23methods/sap.ui.core.util.File.save) are vulnerable to formula injection, or CSV injection.\n\n## Recommendation\n\n### Escape the leading special characters\n\nCSV cells containing a leading special characters such as the equal sign (`=`) may be interpreted as spreadsheet formulas. Therefore, these prefixes should be escaped with surrounding single quotes in order to have them interpreted as literal strings.\n\n### Use a dedicated API function\n\nAs in other injection attacks, it is not recommended to use string concatenation to assemble data passed into a generic file-saving function, even if sanitizers are to be used. Instead, a dedicated library function should be used. For example, if the target being exported is a [sap.m.Table](https://sapui5.hana.ondemand.com/sdk/#/api/sap.m.Table) and the resulting file is intended to be opened using a spreadsheet program, then using one of the API functions provided by [`sap.ui.export.Spreadsheet`](https://sapui5.hana.ondemand.com/#/entity/sap.ui.export.Spreadsheet) is the preferred method of achieving the same exporting functionality.\n\n## Example\n\nThe following controller is exporting a CSV file obtained from an event parameter by surrounding it in a pair of semicolons (`;`) as CSV separators.\n\n``` javascript\nsap.ui.define([\n \"sap/ui/core/Controller\",\n \"sap/ui/core/util/File\"\n ], function(Controller, File) {\n return Controller.extend(\"vulnerable.controller.app\", {\n onSomeEvent: function(oEvent) {\n let response = oEvent.getProperty(\"someProperty\").someField;\n let csvRow = \";\" + response + \";\";\n File.save(csvRow, \"someFile\", \"csv\", \"text/csv\", \"utf-8\");\n }\n });\n });\n```\n\n## References\n\n- OWASP: [CSV Injection](https://owasp.org/www-community/attacks/CSV_Injection)\n- [CWE-1236](https://cwe.mitre.org/data/definitions/1236.html): Improper Neutralization of Formula Elements in a CSV File\n- API Documentation: [`sap.ui.export.Spreadsheet`](https://sapui5.hana.ondemand.com/#/entity/sap.ui.export.Spreadsheet)\n- API Documentation: [`sap.ui.core.util.File.save`](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.util.File%23methods/sap.ui.core.util.File.save)\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-1236" ],
+ "description" : "Saving data from an uncontrolled remote source using filesystem or local storage\n leads to disclosure of sensitive information or forgery of entry.",
+ "id" : "js/ui5-formula-injection",
+ "kind" : "path-problem",
+ "name" : "UI5 Formula Injection",
+ "precision" : "medium",
+ "problem.severity" : "error",
+ "security-severity" : "7.8"
+ }
+ }, {
+ "id" : "js/ui5-log-injection",
+ "name" : "js/ui5-log-injection",
+ "shortDescription" : {
+ "text" : "UI5 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" : "# Log Injection\n\nIf an untrusted input, possibly through a UI5 control, is not sanitized and passed onto a logging function, it is possible that a malicious actor submits a crafted input which might lead to forging log entries. If the entries are logged as plaintext, then newline characters may be inserted by the malicious actor. If the entry is interpreted as HTML, then artitrary HTML code my be included to forge log entries.\n\n## Recommendation\n\nAvoid directly logging untrusted input from a remote source and sanitize it by replaceing characters so that the input no longer contains control characters and substrings that may be interpreted as HTML.\n\n## Examples\n\nThis UI5 application directly outputs what the user submitted via the `sap.m.Input` control.\n\n``` xml\n\n \n\n```\n\n``` javascript\nsap.ui.define(\n [\n \"sap/ui/core/mvc/Controller\",\n \"sap/ui/model/json/JSONModel\",\n \"sap/base/Log/info\",\n ],\n function (Controller, JSONModel, info) {\n return Controller.extend(\"vulnerable.controller.app\", {\n onSearchCompleted: function () {\n var oView = this.getView();\n var oSearchField = oView.byId(\"searchTodoItemsInput\");\n var searchValue = oSearchField.getValue();\n info(searchValue); // Sink\n },\n });\n },\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: [namespace `sap/base/Log`](https://sapui5.hana.ondemand.com/sdk/#api/module:sap/base/Log)\n",
+ "markdown" : "# Log Injection\n\nIf an untrusted input, possibly through a UI5 control, is not sanitized and passed onto a logging function, it is possible that a malicious actor submits a crafted input which might lead to forging log entries. If the entries are logged as plaintext, then newline characters may be inserted by the malicious actor. If the entry is interpreted as HTML, then artitrary HTML code my be included to forge log entries.\n\n## Recommendation\n\nAvoid directly logging untrusted input from a remote source and sanitize it by replaceing characters so that the input no longer contains control characters and substrings that may be interpreted as HTML.\n\n## Examples\n\nThis UI5 application directly outputs what the user submitted via the `sap.m.Input` control.\n\n``` xml\n\n \n\n```\n\n``` javascript\nsap.ui.define(\n [\n \"sap/ui/core/mvc/Controller\",\n \"sap/ui/model/json/JSONModel\",\n \"sap/base/Log/info\",\n ],\n function (Controller, JSONModel, info) {\n return Controller.extend(\"vulnerable.controller.app\", {\n onSearchCompleted: function () {\n var oView = this.getView();\n var oSearchField = oView.byId(\"searchTodoItemsInput\");\n var searchValue = oSearchField.getValue();\n info(searchValue); // Sink\n },\n });\n },\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: [namespace `sap/base/Log`](https://sapui5.hana.ondemand.com/sdk/#api/module:sap/base/Log)\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-117" ],
+ "description" : "Building log entries from user-controlled sources is vulnerable to\n insertion of forged log entries by a malicious user.",
+ "id" : "js/ui5-log-injection",
+ "kind" : "path-problem",
+ "name" : "UI5 Log injection",
+ "precision" : "medium",
+ "problem.severity" : "error",
+ "security-severity" : "7.8"
+ }
+ }, {
+ "id" : "js/ui5-xss",
+ "name" : "js/ui5-xss",
+ "shortDescription" : {
+ "text" : "UI5 Client-side cross-site scripting"
+ },
+ "fullDescription" : {
+ "text" : "Writing user input directly to a UI5 View allows for a cross-site scripting vulnerability."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Client-side cross-site scripting\n\nReceiving text from the user, most notably through a control, and rendering it as HTML in another control can lead to a cross-site scripting vulnerability.\n\n## Recommendation\n\n### Preventing XSS Involving User Defined Control\n\nIf the XSS attack vector includes a user-defined control, then we can mitigate the issue by sanitizing the user-provided input in the implementation of the control:\n- Where possible, define the property type to something other than `string` or `any`. If a value should be used, then opt for the `enum` type which only allows a predefined set of strings.\n- Use escaping functions in `sap.base.security`. Relevant sanitizers include `encodeXML` and `encodeHTML`.\n- When using API with `apiVersion: 2` (Semantic Rendering), do not use `RenderManager.unsafeHtml` unless the control property `sanitizeContent` is set to `true`.\n- When using the now-deprecated older API with `RenderManager.write` or `RenderManager.writeAttribute`, use their respective counterparts `RenderManager.writeEscaped` and `RenderManager.writeAttributeEscaped` which sanitizes their rendered contents.\n\n### Preventing XSS Not Involving User Defined Control\n\nAn XSS attack vector can still exist even when no user-defined control is used. In this case, a model property or a control property act as an intermediate step when external data is passed in.\nIn this case, the UI5 application should not use the property as is, but should sanitize the contents before reading it. Such sanitization can take place in the controller or in the view declaration using expression bindings.\n\n## Example\n\n### Custom Control with Custom Rendering Method\n\nThis custom control `vulnerable.control.xss` calls `unsafeHtml` on a given `RenderManager` instance in its static renderer function. Since its `text` property is an unrestricted string type, it can point to a string with contents that can be interpreted as HTML. If it is the case, `unsafeHtml` will render the string, running a possibly embedded JavaScript code in it.\n\n```javascript\nsap.ui.define([\"sap/ui/core/Control\"], function (Control) {\n return Control.extend(\"vulnerable.control.xss\", {\n metadata: { properties: { text: { type: \"string\" } } },\n renderer: {\n apiVersion: 2,\n render: function (oRm, oControl) {\n oRm.openStart(\"div\", oControl);\n oRm.unsafeHtml(oControl.getText()); // sink\n oRm.close(\"div\");\n }\n }\n });\n})\n```\n\nThis is the same custom control without the possibility of XSS using several means of sanitization: The property `text` is enforced to a non-string type, hence disallows unrestricted strings (This is espcially applicable if the expected input is a number anyways). Also, the `sap.base.security.encodeXML` function is used to escape HTML control characters.\n\n```javascript\nsap.ui.define([\"sap/ui/core/Control\", \"sap/base/security/encodeXML\"], function (Control, encodeXML) {\n return Control.extend(\"vulnerable.control.xss\", {\n metadata: { properties: { text: { type: \"int\" } } }, // constrain the type\n renderer: {\n apiVersion: 2,\n render: function (oRm, oControl) {\n oRm.openStart(\"div\", oControl);\n oRm.unsafeHtml(encodeXML(oControl.getText()); // encode using security functions\n oRm.close(\"div\");\n }\n }\n });\n})\n```\n\n### Library Control\n\nThis example contains only library controls that are not user-defined. The untrusted user input flows from `sap.m.Input` and directly flows out via `sap.ui.core.HTML` through the model property `input` as declared in the `onInit` method of the controller.\n\n``` xml\n\n \t \n \n\n```\n\n``` javascript\nsap.ui.define([\"sap/ui/core/mvc/Controller\", \"sap/ui/model/json/JSONModel\"],\n function (Controller, JSONModel) {\n return Controller.extend(\"vulnerable.controller.app\", {\n onInit: function () {\n var oData = { input: null };\n var oModel = new JSONModel(oData);\n this.getView().setModel(oModel);\n },\n });\n },\n);\n```\n\nThe issue can be resolved by setting the `HTML` control's `sanitizeContent` attribute to true.\n\n``` xml\n\n \n \n\n```\n\n## References\n\n- OWASP: [DOM Based XSS](https://owasp.org/www-community/attacks/DOM_Based_XSS).\n- SAP: [Cross-site Scripting](https://sapui5.hana.ondemand.com/sdk/#/topic/91f0bd316f4d1014b6dd926db0e91070.html) in UI5.\n- SAP: [Prevention of Cross-site Scripting](https://sapui5.hana.ondemand.com/sdk/#/topic/4de64e2e191f4a7297d4fd2d1e233a2d.html) in UI5.\n- SAP: [API Documentation of sap.ui.core.RenderManager](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.RenderManager)\n- SAP: [Documentation of sap.ui.core.HTML](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.HTML%23methods/setSanitizeContent)\n- SAP: [Defining Control Properties](https://sapui5.hana.ondemand.com/sdk/#/topic/ac56d92162ed47ff858fdf1ce26c18c4.html).\n- SAP: [Expression Binding](https://sapui5.hana.ondemand.com/sdk/#/topic/daf6852a04b44d118963968a1239d2c0).\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" : "# Client-side cross-site scripting\n\nReceiving text from the user, most notably through a control, and rendering it as HTML in another control can lead to a cross-site scripting vulnerability.\n\n## Recommendation\n\n### Preventing XSS Involving User Defined Control\n\nIf the XSS attack vector includes a user-defined control, then we can mitigate the issue by sanitizing the user-provided input in the implementation of the control:\n- Where possible, define the property type to something other than `string` or `any`. If a value should be used, then opt for the `enum` type which only allows a predefined set of strings.\n- Use escaping functions in `sap.base.security`. Relevant sanitizers include `encodeXML` and `encodeHTML`.\n- When using API with `apiVersion: 2` (Semantic Rendering), do not use `RenderManager.unsafeHtml` unless the control property `sanitizeContent` is set to `true`.\n- When using the now-deprecated older API with `RenderManager.write` or `RenderManager.writeAttribute`, use their respective counterparts `RenderManager.writeEscaped` and `RenderManager.writeAttributeEscaped` which sanitizes their rendered contents.\n\n### Preventing XSS Not Involving User Defined Control\n\nAn XSS attack vector can still exist even when no user-defined control is used. In this case, a model property or a control property act as an intermediate step when external data is passed in.\nIn this case, the UI5 application should not use the property as is, but should sanitize the contents before reading it. Such sanitization can take place in the controller or in the view declaration using expression bindings.\n\n## Example\n\n### Custom Control with Custom Rendering Method\n\nThis custom control `vulnerable.control.xss` calls `unsafeHtml` on a given `RenderManager` instance in its static renderer function. Since its `text` property is an unrestricted string type, it can point to a string with contents that can be interpreted as HTML. If it is the case, `unsafeHtml` will render the string, running a possibly embedded JavaScript code in it.\n\n```javascript\nsap.ui.define([\"sap/ui/core/Control\"], function (Control) {\n return Control.extend(\"vulnerable.control.xss\", {\n metadata: { properties: { text: { type: \"string\" } } },\n renderer: {\n apiVersion: 2,\n render: function (oRm, oControl) {\n oRm.openStart(\"div\", oControl);\n oRm.unsafeHtml(oControl.getText()); // sink\n oRm.close(\"div\");\n }\n }\n });\n})\n```\n\nThis is the same custom control without the possibility of XSS using several means of sanitization: The property `text` is enforced to a non-string type, hence disallows unrestricted strings (This is espcially applicable if the expected input is a number anyways). Also, the `sap.base.security.encodeXML` function is used to escape HTML control characters.\n\n```javascript\nsap.ui.define([\"sap/ui/core/Control\", \"sap/base/security/encodeXML\"], function (Control, encodeXML) {\n return Control.extend(\"vulnerable.control.xss\", {\n metadata: { properties: { text: { type: \"int\" } } }, // constrain the type\n renderer: {\n apiVersion: 2,\n render: function (oRm, oControl) {\n oRm.openStart(\"div\", oControl);\n oRm.unsafeHtml(encodeXML(oControl.getText()); // encode using security functions\n oRm.close(\"div\");\n }\n }\n });\n})\n```\n\n### Library Control\n\nThis example contains only library controls that are not user-defined. The untrusted user input flows from `sap.m.Input` and directly flows out via `sap.ui.core.HTML` through the model property `input` as declared in the `onInit` method of the controller.\n\n``` xml\n\n \t \n \n\n```\n\n``` javascript\nsap.ui.define([\"sap/ui/core/mvc/Controller\", \"sap/ui/model/json/JSONModel\"],\n function (Controller, JSONModel) {\n return Controller.extend(\"vulnerable.controller.app\", {\n onInit: function () {\n var oData = { input: null };\n var oModel = new JSONModel(oData);\n this.getView().setModel(oModel);\n },\n });\n },\n);\n```\n\nThe issue can be resolved by setting the `HTML` control's `sanitizeContent` attribute to true.\n\n``` xml\n\n \n \n\n```\n\n## References\n\n- OWASP: [DOM Based XSS](https://owasp.org/www-community/attacks/DOM_Based_XSS).\n- SAP: [Cross-site Scripting](https://sapui5.hana.ondemand.com/sdk/#/topic/91f0bd316f4d1014b6dd926db0e91070.html) in UI5.\n- SAP: [Prevention of Cross-site Scripting](https://sapui5.hana.ondemand.com/sdk/#/topic/4de64e2e191f4a7297d4fd2d1e233a2d.html) in UI5.\n- SAP: [API Documentation of sap.ui.core.RenderManager](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.RenderManager)\n- SAP: [Documentation of sap.ui.core.HTML](https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.core.HTML%23methods/setSanitizeContent)\n- SAP: [Defining Control Properties](https://sapui5.hana.ondemand.com/sdk/#/topic/ac56d92162ed47ff858fdf1ce26c18c4.html).\n- SAP: [Expression Binding](https://sapui5.hana.ondemand.com/sdk/#/topic/daf6852a04b44d118963968a1239d2c0).\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" : [ "security", "external/cwe/cwe-079", "external/cwe/cwe-116" ],
+ "description" : "Writing user input directly to a UI5 View allows for\n a cross-site scripting vulnerability.",
+ "id" : "js/ui5-xss",
+ "kind" : "path-problem",
+ "name" : "UI5 Client-side cross-site scripting",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "6.1"
+ }
+ }, {
+ "id" : "js/ui5-clickjacking",
+ "name" : "js/ui5-clickjacking",
+ "shortDescription" : {
+ "text" : "UI5 Clickjacking"
+ },
+ "fullDescription" : {
+ "text" : "The absence of frame options allows for clickjacking."
+ },
+ "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: [Frame Options](https://sapui5.hana.ondemand.com/sdk/#/topic/62d9c4d8f5ad49aa914624af9551beb7.html).\n* SAP: [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: [Frame Options](https://sapui5.hana.ondemand.com/sdk/#/topic/62d9c4d8f5ad49aa914624af9551beb7.html).\n* SAP: [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", "external/cwe/cwe-451" ],
+ "description" : "The absence of frame options allows for clickjacking.",
+ "id" : "js/ui5-clickjacking",
+ "kind" : "problem",
+ "name" : "UI5 Clickjacking",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "6.1"
+ }
+ } ],
+ "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.3.0+d4326cab70648ae61cc6f8988b7d2cb72ceb5e13",
+ "rules" : [ {
+ "id" : "js/cap-sql-injection",
+ "name" : "js/cap-sql-injection",
+ "shortDescription" : {
+ "text" : "Database query built from user-controlled sources with additional heuristic sources"
+ },
+ "fullDescription" : {
+ "text" : "Building a database query from user-controlled sources is vulnerable to insertion of malicious code by the user."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "properties" : {
+ "tags" : [ "security" ],
+ "description" : "Building a database 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" : "Database query built from user-controlled sources with additional heuristic sources",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "8.8"
+ }
+ }, {
+ "id" : "js/cap-log-injection",
+ "name" : "js/cap-log-injection",
+ "shortDescription" : {
+ "text" : "Uncontrolled data in logging call"
+ },
+ "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"
+ },
+ "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" : "Uncontrolled data in logging call",
+ "precision" : "medium",
+ "problem.severity" : "error",
+ "security-severity" : "7.8"
+ }
+ } ],
+ "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" : "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.7+766e0e61eddec865422fbc6dbe70b69b47fb0eab",
+ "notifications" : [ {
+ "id" : "js/diagnostics/extraction-errors",
+ "name" : "js/diagnostics/extraction-errors",
+ "shortDescription" : {
+ "text" : "Extraction errors"
+ },
+ "fullDescription" : {
+ "text" : "List all extraction errors for files in the source code directory."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true
+ },
+ "properties" : {
+ "description" : "List all extraction errors for files in the source code directory.",
+ "id" : "js/diagnostics/extraction-errors",
+ "kind" : "diagnostic",
+ "name" : "Extraction errors"
+ }
+ }, {
+ "id" : "js/diagnostics/successfully-extracted-files",
+ "name" : "js/diagnostics/successfully-extracted-files",
+ "shortDescription" : {
+ "text" : "Extracted files"
+ },
+ "fullDescription" : {
+ "text" : "Lists all files in the source code directory that were extracted."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true
+ },
+ "properties" : {
+ "tags" : [ "successfully-extracted-files" ],
+ "description" : "Lists all files in the source code directory that were extracted.",
+ "id" : "js/diagnostics/successfully-extracted-files",
+ "kind" : "diagnostic",
+ "name" : "Extracted files"
+ }
+ } ],
+ "rules" : [ {
+ "id" : "js/unvalidated-dynamic-method-call",
+ "name" : "js/unvalidated-dynamic-method-call",
+ "shortDescription" : {
+ "text" : "Unvalidated dynamic method call"
+ },
+ "fullDescription" : {
+ "text" : "Calling a method with a user-controlled name may dispatch to an unexpected target, which could cause an exception."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Unvalidated dynamic method call\nJavaScript makes it easy to look up object properties dynamically at runtime. In particular, methods can be looked up by name and then called. However, if the method name is user-controlled, an attacker could choose a name that makes the application invoke an unexpected method, which may cause a runtime exception. If this exception is not handled, it could be used to mount a denial-of-service attack.\n\nFor example, there might not be a method of the given name, or the result of the lookup might not be a function. In either case the method call will throw a `TypeError` at runtime.\n\nAnother, more subtle example is where the result of the lookup is a standard library method from `Object.prototype`, which most objects have on their prototype chain. Examples of such methods include `valueOf`, `hasOwnProperty` and `__defineSetter__`. If the method call passes the wrong number or kind of arguments to these methods, they will throw an exception.\n\n\n## Recommendation\nIt is best to avoid dynamic method lookup involving user-controlled names altogether, for instance by using a `Map` instead of a plain object.\n\nIf the dynamic method lookup cannot be avoided, consider whitelisting permitted method names. At the very least, check that the method is an own property and not inherited from the prototype object. If the object on which the method is looked up contains properties that are not methods, you should additionally check that the result of the lookup is a function. Even if the object only contains methods, it is still a good idea to perform this check in case other properties are added to the object later on.\n\n\n## Example\nIn the following example, an HTTP request parameter `action` property is used to dynamically look up a function in the `actions` map, which is then invoked with the `payload` parameter as its argument.\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\nvar actions = {\n play(data) {\n // ...\n },\n pause(data) {\n // ...\n }\n}\n\napp.get('/perform/:action/:payload', function(req, res) {\n let action = actions[req.params.action];\n // BAD: `action` may not be a function\n res.end(action(req.params.payload));\n});\n\n```\nThe intention is to allow clients to invoke the `play` or `pause` method, but there is no check that `action` is actually the name of a method stored in `actions`. If, for example, `action` is `rewind`, `action` will be `undefined` and the call will result in a runtime error.\n\nThe easiest way to prevent this is to turn `actions` into a `Map` and using `Map.prototype.has` to check whether the method name is valid before looking it up.\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\nvar actions = new Map();\nactions.set(\"play\", function play(data) {\n // ...\n});\nactions.set(\"pause\", function pause(data) {\n // ...\n});\n\napp.get('/perform/:action/:payload', function(req, res) {\n if (actions.has(req.params.action)) {\n if (typeof actions.get(req.params.action) === 'function'){\n let action = actions.get(req.params.action);\n }\n // GOOD: `action` is either the `play` or the `pause` function from above\n res.end(action(req.params.payload));\n } else {\n res.end(\"Unsupported action.\");\n }\n});\n\n```\nIf `actions` cannot be turned into a `Map`, a `hasOwnProperty` check should be added to validate the method name:\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\nvar actions = {\n play(data) {\n // ...\n },\n pause(data) {\n // ...\n }\n}\n\napp.get('/perform/:action/:payload', function(req, res) {\n if (actions.hasOwnProperty(req.params.action)) {\n let action = actions[req.params.action];\n if (typeof action === 'function') {\n // GOOD: `action` is an own method of `actions`\n res.end(action(req.params.payload));\n return;\n }\n }\n res.end(\"Unsupported action.\");\n});\n\n```\n\n## References\n* OWASP: [Denial of Service](https://www.owasp.org/index.php/Denial_of_Service).\n* MDN: [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map).\n* MDN: [Object.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype).\n* Common Weakness Enumeration: [CWE-754](https://cwe.mitre.org/data/definitions/754.html).\n",
+ "markdown" : "# Unvalidated dynamic method call\nJavaScript makes it easy to look up object properties dynamically at runtime. In particular, methods can be looked up by name and then called. However, if the method name is user-controlled, an attacker could choose a name that makes the application invoke an unexpected method, which may cause a runtime exception. If this exception is not handled, it could be used to mount a denial-of-service attack.\n\nFor example, there might not be a method of the given name, or the result of the lookup might not be a function. In either case the method call will throw a `TypeError` at runtime.\n\nAnother, more subtle example is where the result of the lookup is a standard library method from `Object.prototype`, which most objects have on their prototype chain. Examples of such methods include `valueOf`, `hasOwnProperty` and `__defineSetter__`. If the method call passes the wrong number or kind of arguments to these methods, they will throw an exception.\n\n\n## Recommendation\nIt is best to avoid dynamic method lookup involving user-controlled names altogether, for instance by using a `Map` instead of a plain object.\n\nIf the dynamic method lookup cannot be avoided, consider whitelisting permitted method names. At the very least, check that the method is an own property and not inherited from the prototype object. If the object on which the method is looked up contains properties that are not methods, you should additionally check that the result of the lookup is a function. Even if the object only contains methods, it is still a good idea to perform this check in case other properties are added to the object later on.\n\n\n## Example\nIn the following example, an HTTP request parameter `action` property is used to dynamically look up a function in the `actions` map, which is then invoked with the `payload` parameter as its argument.\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\nvar actions = {\n play(data) {\n // ...\n },\n pause(data) {\n // ...\n }\n}\n\napp.get('/perform/:action/:payload', function(req, res) {\n let action = actions[req.params.action];\n // BAD: `action` may not be a function\n res.end(action(req.params.payload));\n});\n\n```\nThe intention is to allow clients to invoke the `play` or `pause` method, but there is no check that `action` is actually the name of a method stored in `actions`. If, for example, `action` is `rewind`, `action` will be `undefined` and the call will result in a runtime error.\n\nThe easiest way to prevent this is to turn `actions` into a `Map` and using `Map.prototype.has` to check whether the method name is valid before looking it up.\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\nvar actions = new Map();\nactions.set(\"play\", function play(data) {\n // ...\n});\nactions.set(\"pause\", function pause(data) {\n // ...\n});\n\napp.get('/perform/:action/:payload', function(req, res) {\n if (actions.has(req.params.action)) {\n if (typeof actions.get(req.params.action) === 'function'){\n let action = actions.get(req.params.action);\n }\n // GOOD: `action` is either the `play` or the `pause` function from above\n res.end(action(req.params.payload));\n } else {\n res.end(\"Unsupported action.\");\n }\n});\n\n```\nIf `actions` cannot be turned into a `Map`, a `hasOwnProperty` check should be added to validate the method name:\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\nvar actions = {\n play(data) {\n // ...\n },\n pause(data) {\n // ...\n }\n}\n\napp.get('/perform/:action/:payload', function(req, res) {\n if (actions.hasOwnProperty(req.params.action)) {\n let action = actions[req.params.action];\n if (typeof action === 'function') {\n // GOOD: `action` is an own method of `actions`\n res.end(action(req.params.payload));\n return;\n }\n }\n res.end(\"Unsupported action.\");\n});\n\n```\n\n## References\n* OWASP: [Denial of Service](https://www.owasp.org/index.php/Denial_of_Service).\n* MDN: [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map).\n* MDN: [Object.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype).\n* Common Weakness Enumeration: [CWE-754](https://cwe.mitre.org/data/definitions/754.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-754" ],
+ "description" : "Calling a method with a user-controlled name may dispatch to\n an unexpected target, which could cause an exception.",
+ "id" : "js/unvalidated-dynamic-method-call",
+ "kind" : "path-problem",
+ "name" : "Unvalidated dynamic method call",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "7.5"
+ }
+ }, {
+ "id" : "js/functionality-from-untrusted-source",
+ "name" : "js/functionality-from-untrusted-source",
+ "shortDescription" : {
+ "text" : "Inclusion of functionality from an untrusted source"
+ },
+ "fullDescription" : {
+ "text" : "Including functionality from an untrusted source may allow an attacker to control the functionality and execute arbitrary code."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Inclusion of functionality from an untrusted source\nIncluding a resource from an untrusted source or using an untrusted channel may allow an attacker to include arbitrary code in the response. When including an external resource (for example, a `script` element or an `iframe` element) on a page, it is important to ensure that the received data is not malicious.\n\nWhen including external resources, it is possible to verify that the responding server is the intended one by using an `https` URL. This prevents a MITM (man-in-the-middle) attack where an attacker might have been able to spoof a server response.\n\nEven when `https` is used, an attacker might still compromise the server. When you use a `script` element, you can check for subresource integrity - that is, you can check the contents of the data received by supplying a cryptographic digest of the expected sources to the `script` element. The script will only load sources that match the digest and an attacker will be unable to modify the script even when the server is compromised.\n\nSubresource integrity checking is commonly recommended when importing a fixed version of a library - for example, from a CDN (content-delivery network). Then, the fixed digest of that version of the library can easily be added to the `script` element's `integrity` attribute.\n\n\n## Recommendation\nWhen an `iframe` element is used to embed a page, it is important to use an `https` URL.\n\nWhen using a `script` element to load a script, it is important to use an `https` URL and to consider checking subresource integrity.\n\n\n## Example\nThe following example loads the jQuery library from the jQuery CDN without using `https` and without checking subresource integrity.\n\n\n```html\n\n \n jQuery demo\n \n \n \n ...\n \n\n```\nInstead, loading jQuery from the same domain using `https` and checking subresource integrity is recommended, as in the next example.\n\n\n```html\n\n \n jQuery demo\n \n \n \n ...\n \n\n```\n\n## References\n* MDN: [Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)\n* Smashing Magazine: [Understanding Subresource Integrity](https://www.smashingmagazine.com/2019/04/understanding-subresource-integrity/)\n* Common Weakness Enumeration: [CWE-830](https://cwe.mitre.org/data/definitions/830.html).\n",
+ "markdown" : "# Inclusion of functionality from an untrusted source\nIncluding a resource from an untrusted source or using an untrusted channel may allow an attacker to include arbitrary code in the response. When including an external resource (for example, a `script` element or an `iframe` element) on a page, it is important to ensure that the received data is not malicious.\n\nWhen including external resources, it is possible to verify that the responding server is the intended one by using an `https` URL. This prevents a MITM (man-in-the-middle) attack where an attacker might have been able to spoof a server response.\n\nEven when `https` is used, an attacker might still compromise the server. When you use a `script` element, you can check for subresource integrity - that is, you can check the contents of the data received by supplying a cryptographic digest of the expected sources to the `script` element. The script will only load sources that match the digest and an attacker will be unable to modify the script even when the server is compromised.\n\nSubresource integrity checking is commonly recommended when importing a fixed version of a library - for example, from a CDN (content-delivery network). Then, the fixed digest of that version of the library can easily be added to the `script` element's `integrity` attribute.\n\n\n## Recommendation\nWhen an `iframe` element is used to embed a page, it is important to use an `https` URL.\n\nWhen using a `script` element to load a script, it is important to use an `https` URL and to consider checking subresource integrity.\n\n\n## Example\nThe following example loads the jQuery library from the jQuery CDN without using `https` and without checking subresource integrity.\n\n\n```html\n\n \n jQuery demo\n \n \n \n ...\n \n\n```\nInstead, loading jQuery from the same domain using `https` and checking subresource integrity is recommended, as in the next example.\n\n\n```html\n\n \n jQuery demo\n \n \n \n ...\n \n\n```\n\n## References\n* MDN: [Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)\n* Smashing Magazine: [Understanding Subresource Integrity](https://www.smashingmagazine.com/2019/04/understanding-subresource-integrity/)\n* Common Weakness Enumeration: [CWE-830](https://cwe.mitre.org/data/definitions/830.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-830" ],
+ "description" : "Including functionality from an untrusted source may allow\n an attacker to control the functionality and execute arbitrary code.",
+ "id" : "js/functionality-from-untrusted-source",
+ "kind" : "problem",
+ "name" : "Inclusion of functionality from an untrusted source",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "6.0"
+ }
+ }, {
+ "id" : "js/hardcoded-credentials",
+ "name" : "js/hardcoded-credentials",
+ "shortDescription" : {
+ "text" : "Hard-coded credentials"
+ },
+ "fullDescription" : {
+ "text" : "Hard-coding credentials in source code may enable an attacker to gain unauthorized access."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Hard-coded credentials\nIncluding unencrypted hard-coded authentication credentials in source code is dangerous because the credentials may be easily discovered. For example, the code may be open source, or it may be leaked or accidentally revealed, making the credentials visible to an attacker. This, in turn, might enable them to gain unauthorized access, or to obtain privileged information.\n\n\n## Recommendation\nRemove hard-coded credentials, such as user names, passwords and certificates, from source code. Instead, place them in configuration files, environment variables or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access.\n\n\n## Example\nThe following code example connects to an HTTP request using an hard-codes authentication header:\n\n\n```javascript\nlet base64 = require('base-64');\n\nlet url = 'http://example.org/auth';\nlet username = 'user';\nlet password = 'passwd';\n\nlet headers = new Headers();\n\nheaders.append('Content-Type', 'text/json');\nheaders.append('Authorization', 'Basic' + base64.encode(username + \":\" + password));\n\nfetch(url, {\n method:'GET',\n headers: headers\n })\n.then(response => response.json())\n.then(json => console.log(json))\n.done();\n\n```\nInstead, user name and password can be supplied through the environment variables `username` and `password`, which can be set externally without hard-coding credentials in the source code.\n\n\n```javascript\nlet base64 = require('base-64');\n\nlet url = 'http://example.org/auth';\nlet username = process.env.USERNAME;\nlet password = process.env.PASSWORD;\n\nlet headers = new Headers();\n\nheaders.append('Content-Type', 'text/json');\nheaders.append('Authorization', 'Basic' + base64.encode(username + \":\" + password));\n\nfetch(url, {\n method:'GET',\n headers: headers\n })\n.then(response => response.json())\n.then(json => console.log(json))\n.done();\n\n```\n\n## Example\nThe following code example connects to a Postgres database using the `pg` package and hard-codes user name and password:\n\n\n```javascript\nconst pg = require(\"pg\");\n\nconst client = new pg.Client({\n user: \"bob\",\n host: \"database.server.com\",\n database: \"mydb\",\n password: \"correct-horse-battery-staple\",\n port: 3211\n});\nclient.connect();\n\n```\nInstead, user name and password can be supplied through the environment variables `PGUSER` and `PGPASSWORD`, which can be set externally without hard-coding credentials in the source code.\n\n\n## References\n* OWASP: [Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password).\n* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html).\n* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html).\n* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html).\n",
+ "markdown" : "# Hard-coded credentials\nIncluding unencrypted hard-coded authentication credentials in source code is dangerous because the credentials may be easily discovered. For example, the code may be open source, or it may be leaked or accidentally revealed, making the credentials visible to an attacker. This, in turn, might enable them to gain unauthorized access, or to obtain privileged information.\n\n\n## Recommendation\nRemove hard-coded credentials, such as user names, passwords and certificates, from source code. Instead, place them in configuration files, environment variables or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access.\n\n\n## Example\nThe following code example connects to an HTTP request using an hard-codes authentication header:\n\n\n```javascript\nlet base64 = require('base-64');\n\nlet url = 'http://example.org/auth';\nlet username = 'user';\nlet password = 'passwd';\n\nlet headers = new Headers();\n\nheaders.append('Content-Type', 'text/json');\nheaders.append('Authorization', 'Basic' + base64.encode(username + \":\" + password));\n\nfetch(url, {\n method:'GET',\n headers: headers\n })\n.then(response => response.json())\n.then(json => console.log(json))\n.done();\n\n```\nInstead, user name and password can be supplied through the environment variables `username` and `password`, which can be set externally without hard-coding credentials in the source code.\n\n\n```javascript\nlet base64 = require('base-64');\n\nlet url = 'http://example.org/auth';\nlet username = process.env.USERNAME;\nlet password = process.env.PASSWORD;\n\nlet headers = new Headers();\n\nheaders.append('Content-Type', 'text/json');\nheaders.append('Authorization', 'Basic' + base64.encode(username + \":\" + password));\n\nfetch(url, {\n method:'GET',\n headers: headers\n })\n.then(response => response.json())\n.then(json => console.log(json))\n.done();\n\n```\n\n## Example\nThe following code example connects to a Postgres database using the `pg` package and hard-codes user name and password:\n\n\n```javascript\nconst pg = require(\"pg\");\n\nconst client = new pg.Client({\n user: \"bob\",\n host: \"database.server.com\",\n database: \"mydb\",\n password: \"correct-horse-battery-staple\",\n port: 3211\n});\nclient.connect();\n\n```\nInstead, user name and password can be supplied through the environment variables `PGUSER` and `PGPASSWORD`, which can be set externally without hard-coding credentials in the source code.\n\n\n## References\n* OWASP: [Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password).\n* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html).\n* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html).\n* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-259", "external/cwe/cwe-321", "external/cwe/cwe-798" ],
+ "description" : "Hard-coding credentials in source code may enable an attacker\n to gain unauthorized access.",
+ "id" : "js/hardcoded-credentials",
+ "kind" : "path-problem",
+ "name" : "Hard-coded credentials",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "9.8"
+ }
+ }, {
+ "id" : "js/disabling-certificate-validation",
+ "name" : "js/disabling-certificate-validation",
+ "shortDescription" : {
+ "text" : "Disabling certificate validation"
+ },
+ "fullDescription" : {
+ "text" : "Disabling cryptographic certificate validation can cause security vulnerabilities."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Disabling certificate validation\nCertificate validation is the standard authentication method of a secure TLS connection. Without it, there is no guarantee about who the other party of a TLS connection is, making man-in-the-middle attacks more likely to occur\n\nWhen testing software that uses TLS connections, it may be useful to disable the certificate validation temporarily. But disabling it in production environments is strongly discouraged, unless an alternative method of authentication is used.\n\n\n## Recommendation\nDo not disable certificate validation for TLS connections.\n\n\n## Example\nThe following example shows a HTTPS connection that transfers confidential information to a remote server. But the connection is not secure since the `rejectUnauthorized` option of the connection is set to `false`. As a consequence, anyone can impersonate the remote server, and receive the confidential information.\n\n\n```javascript\nlet https = require(\"https\");\n\nhttps.request(\n {\n hostname: \"secure.my-online-bank.com\",\n port: 443,\n method: \"POST\",\n path: \"send-confidential-information\",\n rejectUnauthorized: false // BAD\n },\n response => {\n // ... communicate with secure.my-online-bank.com\n }\n);\n\n```\nTo make the connection secure, the `rejectUnauthorized` option should have its default value, or be explicitly set to `true`.\n\n\n## References\n* Wikipedia: [Transport Layer Security (TLS)](https://en.wikipedia.org/wiki/Transport_Layer_Security)\n* Wikipedia: [Man-in-the-middle attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack)\n* Node.js: [TLS (SSL)](https://nodejs.org/api/tls.html)\n* Common Weakness Enumeration: [CWE-295](https://cwe.mitre.org/data/definitions/295.html).\n* Common Weakness Enumeration: [CWE-297](https://cwe.mitre.org/data/definitions/297.html).\n",
+ "markdown" : "# Disabling certificate validation\nCertificate validation is the standard authentication method of a secure TLS connection. Without it, there is no guarantee about who the other party of a TLS connection is, making man-in-the-middle attacks more likely to occur\n\nWhen testing software that uses TLS connections, it may be useful to disable the certificate validation temporarily. But disabling it in production environments is strongly discouraged, unless an alternative method of authentication is used.\n\n\n## Recommendation\nDo not disable certificate validation for TLS connections.\n\n\n## Example\nThe following example shows a HTTPS connection that transfers confidential information to a remote server. But the connection is not secure since the `rejectUnauthorized` option of the connection is set to `false`. As a consequence, anyone can impersonate the remote server, and receive the confidential information.\n\n\n```javascript\nlet https = require(\"https\");\n\nhttps.request(\n {\n hostname: \"secure.my-online-bank.com\",\n port: 443,\n method: \"POST\",\n path: \"send-confidential-information\",\n rejectUnauthorized: false // BAD\n },\n response => {\n // ... communicate with secure.my-online-bank.com\n }\n);\n\n```\nTo make the connection secure, the `rejectUnauthorized` option should have its default value, or be explicitly set to `true`.\n\n\n## References\n* Wikipedia: [Transport Layer Security (TLS)](https://en.wikipedia.org/wiki/Transport_Layer_Security)\n* Wikipedia: [Man-in-the-middle attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack)\n* Node.js: [TLS (SSL)](https://nodejs.org/api/tls.html)\n* Common Weakness Enumeration: [CWE-295](https://cwe.mitre.org/data/definitions/295.html).\n* Common Weakness Enumeration: [CWE-297](https://cwe.mitre.org/data/definitions/297.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-295", "external/cwe/cwe-297" ],
+ "description" : "Disabling cryptographic certificate validation can cause security vulnerabilities.",
+ "id" : "js/disabling-certificate-validation",
+ "kind" : "problem",
+ "name" : "Disabling certificate validation",
+ "precision" : "very-high",
+ "problem.severity" : "error",
+ "security-severity" : "7.5"
+ }
+ }, {
+ "id" : "js/server-crash",
+ "name" : "js/server-crash",
+ "shortDescription" : {
+ "text" : "Server crash"
+ },
+ "fullDescription" : {
+ "text" : "A server that can be forced to crash may be vulnerable to denial-of-service attacks."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Server crash\nServers handle requests from clients until terminated deliberately by a server administrator. A client request that results in an uncaught server-side exception causes the current server response generation to fail, and should not have an effect on subsequent client requests.\n\nUnder some circumstances, uncaught exceptions can however cause the entire server to terminate abruptly. Such a behavior is highly undesirable, especially if it gives malicious users the ability to turn off the server at will, which is an efficient denial-of-service attack.\n\n\n## Recommendation\nEnsure that the processing of client requests can not cause uncaught exceptions to terminate the entire server abruptly.\n\n\n## Example\nThe following server code checks if a client-provided file path is valid before saving data to that path. It would be reasonable to expect that the server responds with an error in case the request contains an invalid file path. However, the server instead throws an exception, which is uncaught in the context of the asynchronous callback invocation (`fs.access(...)`). This causes the entire server to terminate abruptly.\n\n\n```javascript\nconst express = require(\"express\"),\n fs = require(\"fs\");\n\nfunction save(rootDir, path, content) {\n if (!isValidPath(rootDir, req.query.filePath)) {\n throw new Error(`Invalid filePath: ${req.query.filePath}`); // BAD crashes the server\n }\n // write content to disk\n}\n\nexpress().post(\"/save\", (req, res) => {\n fs.access(rootDir, (err) => {\n if (err) {\n console.error(\n `Server setup is corrupted, ${rootDir} cannot be accessed!`\n );\n res.status(500);\n res.end();\n return;\n }\n save(rootDir, req.query.path, req.body);\n res.status(200);\n res.end();\n });\n});\n\n```\nTo remedy this, the server can catch the exception explicitly with a `try/catch` block, and generate an appropriate error response instead:\n\n\n```javascript\n// ...\nexpress().post(\"/save\", (req, res) => {\n fs.access(rootDir, (err) => {\n // ...\n try {\n save(rootDir, req.query.path, req.body); // GOOD exception is caught below\n res.status(200);\n res.end();\n } catch (e) {\n res.status(500);\n res.end();\n }\n });\n});\n\n```\nTo simplify exception handling, it may be advisable to switch to async/await syntax instead of using callbacks, which allows wrapping the entire request handler in a `try/catch` block:\n\n\n```javascript\n// ...\nexpress().post(\"/save\", async (req, res) => {\n try {\n await fs.promises.access(rootDir);\n save(rootDir, req.query.path, req.body); // GOOD exception is caught below\n res.status(200);\n res.end();\n } catch (e) {\n res.status(500);\n res.end();\n }\n});\n\n```\n\n## References\n* Common Weakness Enumeration: [CWE-248](https://cwe.mitre.org/data/definitions/248.html).\n* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html).\n",
+ "markdown" : "# Server crash\nServers handle requests from clients until terminated deliberately by a server administrator. A client request that results in an uncaught server-side exception causes the current server response generation to fail, and should not have an effect on subsequent client requests.\n\nUnder some circumstances, uncaught exceptions can however cause the entire server to terminate abruptly. Such a behavior is highly undesirable, especially if it gives malicious users the ability to turn off the server at will, which is an efficient denial-of-service attack.\n\n\n## Recommendation\nEnsure that the processing of client requests can not cause uncaught exceptions to terminate the entire server abruptly.\n\n\n## Example\nThe following server code checks if a client-provided file path is valid before saving data to that path. It would be reasonable to expect that the server responds with an error in case the request contains an invalid file path. However, the server instead throws an exception, which is uncaught in the context of the asynchronous callback invocation (`fs.access(...)`). This causes the entire server to terminate abruptly.\n\n\n```javascript\nconst express = require(\"express\"),\n fs = require(\"fs\");\n\nfunction save(rootDir, path, content) {\n if (!isValidPath(rootDir, req.query.filePath)) {\n throw new Error(`Invalid filePath: ${req.query.filePath}`); // BAD crashes the server\n }\n // write content to disk\n}\n\nexpress().post(\"/save\", (req, res) => {\n fs.access(rootDir, (err) => {\n if (err) {\n console.error(\n `Server setup is corrupted, ${rootDir} cannot be accessed!`\n );\n res.status(500);\n res.end();\n return;\n }\n save(rootDir, req.query.path, req.body);\n res.status(200);\n res.end();\n });\n});\n\n```\nTo remedy this, the server can catch the exception explicitly with a `try/catch` block, and generate an appropriate error response instead:\n\n\n```javascript\n// ...\nexpress().post(\"/save\", (req, res) => {\n fs.access(rootDir, (err) => {\n // ...\n try {\n save(rootDir, req.query.path, req.body); // GOOD exception is caught below\n res.status(200);\n res.end();\n } catch (e) {\n res.status(500);\n res.end();\n }\n });\n});\n\n```\nTo simplify exception handling, it may be advisable to switch to async/await syntax instead of using callbacks, which allows wrapping the entire request handler in a `try/catch` block:\n\n\n```javascript\n// ...\nexpress().post(\"/save\", async (req, res) => {\n try {\n await fs.promises.access(rootDir);\n save(rootDir, req.query.path, req.body); // GOOD exception is caught below\n res.status(200);\n res.end();\n } catch (e) {\n res.status(500);\n res.end();\n }\n});\n\n```\n\n## References\n* Common Weakness Enumeration: [CWE-248](https://cwe.mitre.org/data/definitions/248.html).\n* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-248", "external/cwe/cwe-730" ],
+ "description" : "A server that can be forced to crash may be vulnerable to denial-of-service\n attacks.",
+ "id" : "js/server-crash",
+ "kind" : "path-problem",
+ "name" : "Server crash",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "7.5"
+ }
+ }, {
+ "id" : "js/regex-injection",
+ "name" : "js/regex-injection",
+ "shortDescription" : {
+ "text" : "Regular expression injection"
+ },
+ "fullDescription" : {
+ "text" : "User input should not be used in regular expressions without first being escaped, otherwise a malicious user may be able to inject an expression that could require exponential time on certain inputs."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Regular expression injection\nConstructing a regular expression with unsanitized user input is dangerous as a malicious user may be able to modify the meaning of the expression. In particular, such a user may be able to provide a regular expression fragment that takes exponential time in the worst case, and use that to perform a Denial of Service attack.\n\n\n## Recommendation\nBefore embedding user input into a regular expression, use a sanitization function such as lodash's `_.escapeRegExp` to escape meta-characters that have special meaning.\n\n\n## Example\nThe following example shows a HTTP request parameter that is used to construct a regular expression without sanitizing it first:\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\napp.get('/findKey', function(req, res) {\n var key = req.param(\"key\"), input = req.param(\"input\");\n\n // BAD: Unsanitized user input is used to construct a regular expression\n var re = new RegExp(\"\\\\b\" + key + \"=(.*)\\n\");\n});\n\n```\nInstead, the request parameter should be sanitized first, for example using the function `_.escapeRegExp` from the lodash package. This ensures that the user cannot insert characters which have a special meaning in regular expressions.\n\n\n```javascript\nvar express = require('express');\nvar _ = require('lodash');\nvar app = express();\n\napp.get('/findKey', function(req, res) {\n var key = req.param(\"key\"), input = req.param(\"input\");\n\n // GOOD: User input is sanitized before constructing the regex\n var safeKey = _.escapeRegExp(key);\n var re = new RegExp(\"\\\\b\" + safeKey + \"=(.*)\\n\");\n});\n\n```\n\n## References\n* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS).\n* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS).\n* npm: [lodash](https://www.npmjs.com/package/lodash).\n* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html).\n* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html).\n",
+ "markdown" : "# Regular expression injection\nConstructing a regular expression with unsanitized user input is dangerous as a malicious user may be able to modify the meaning of the expression. In particular, such a user may be able to provide a regular expression fragment that takes exponential time in the worst case, and use that to perform a Denial of Service attack.\n\n\n## Recommendation\nBefore embedding user input into a regular expression, use a sanitization function such as lodash's `_.escapeRegExp` to escape meta-characters that have special meaning.\n\n\n## Example\nThe following example shows a HTTP request parameter that is used to construct a regular expression without sanitizing it first:\n\n\n```javascript\nvar express = require('express');\nvar app = express();\n\napp.get('/findKey', function(req, res) {\n var key = req.param(\"key\"), input = req.param(\"input\");\n\n // BAD: Unsanitized user input is used to construct a regular expression\n var re = new RegExp(\"\\\\b\" + key + \"=(.*)\\n\");\n});\n\n```\nInstead, the request parameter should be sanitized first, for example using the function `_.escapeRegExp` from the lodash package. This ensures that the user cannot insert characters which have a special meaning in regular expressions.\n\n\n```javascript\nvar express = require('express');\nvar _ = require('lodash');\nvar app = express();\n\napp.get('/findKey', function(req, res) {\n var key = req.param(\"key\"), input = req.param(\"input\");\n\n // GOOD: User input is sanitized before constructing the regex\n var safeKey = _.escapeRegExp(key);\n var re = new RegExp(\"\\\\b\" + safeKey + \"=(.*)\\n\");\n});\n\n```\n\n## References\n* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS).\n* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS).\n* npm: [lodash](https://www.npmjs.com/package/lodash).\n* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html).\n* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-730", "external/cwe/cwe-400" ],
+ "description" : "User input should not be used in regular expressions without first being escaped,\n otherwise a malicious user may be able to inject an expression that could require\n exponential time on certain inputs.",
+ "id" : "js/regex-injection",
+ "kind" : "path-problem",
+ "name" : "Regular expression injection",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "7.5"
+ }
+ }, {
+ "id" : "js/exposure-of-private-files",
+ "name" : "js/exposure-of-private-files",
+ "shortDescription" : {
+ "text" : "Exposure of private files"
+ },
+ "fullDescription" : {
+ "text" : "Exposing a node_modules folder, or the project folder to the public, can cause exposure of private information."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Exposure of private files\nLibraries like `express` provide easy methods for serving entire directories of static files from a web server. However, using these can sometimes lead to accidental information exposure. If for example the `node_modules` folder is served, then an attacker can access the `_where` field from a `package.json` file, which gives access to the absolute path of the file.\n\n\n## Recommendation\nLimit which folders of static files are served from a web server.\n\n\n## Example\nIn the example below, all the files from the `node_modules` are served. This allows clients to easily access all the files inside that folder, which includes potentially private information inside `package.json` files.\n\n\n```javascript\n\nvar express = require('express');\n\nvar app = express();\n\napp.use('/node_modules', express.static(path.resolve(__dirname, '../node_modules')));\n```\nThe issue has been fixed below by only serving specific folders within the `node_modules` folder.\n\n\n```javascript\n\nvar express = require('express');\n\nvar app = express();\n\napp.use(\"jquery\", express.static('./node_modules/jquery/dist'));\napp.use(\"bootstrap\", express.static('./node_modules/bootstrap/dist'));\n```\n\n## References\n* OWASP: [Sensitive Data Exposure](https://www.owasp.org/index.php/Top_10-2017_A3-Sensitive_Data_Exposure).\n* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html).\n* Common Weakness Enumeration: [CWE-219](https://cwe.mitre.org/data/definitions/219.html).\n* Common Weakness Enumeration: [CWE-548](https://cwe.mitre.org/data/definitions/548.html).\n",
+ "markdown" : "# Exposure of private files\nLibraries like `express` provide easy methods for serving entire directories of static files from a web server. However, using these can sometimes lead to accidental information exposure. If for example the `node_modules` folder is served, then an attacker can access the `_where` field from a `package.json` file, which gives access to the absolute path of the file.\n\n\n## Recommendation\nLimit which folders of static files are served from a web server.\n\n\n## Example\nIn the example below, all the files from the `node_modules` are served. This allows clients to easily access all the files inside that folder, which includes potentially private information inside `package.json` files.\n\n\n```javascript\n\nvar express = require('express');\n\nvar app = express();\n\napp.use('/node_modules', express.static(path.resolve(__dirname, '../node_modules')));\n```\nThe issue has been fixed below by only serving specific folders within the `node_modules` folder.\n\n\n```javascript\n\nvar express = require('express');\n\nvar app = express();\n\napp.use(\"jquery\", express.static('./node_modules/jquery/dist'));\napp.use(\"bootstrap\", express.static('./node_modules/bootstrap/dist'));\n```\n\n## References\n* OWASP: [Sensitive Data Exposure](https://www.owasp.org/index.php/Top_10-2017_A3-Sensitive_Data_Exposure).\n* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html).\n* Common Weakness Enumeration: [CWE-219](https://cwe.mitre.org/data/definitions/219.html).\n* Common Weakness Enumeration: [CWE-548](https://cwe.mitre.org/data/definitions/548.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-200", "external/cwe/cwe-219", "external/cwe/cwe-548" ],
+ "description" : "Exposing a node_modules folder, or the project folder to the public, can cause exposure\n of private information.",
+ "id" : "js/exposure-of-private-files",
+ "kind" : "problem",
+ "name" : "Exposure of private files",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "6.5"
+ }
+ }, {
+ "id" : "js/unsafe-deserialization",
+ "name" : "js/unsafe-deserialization",
+ "shortDescription" : {
+ "text" : "Deserialization of user-controlled data"
+ },
+ "fullDescription" : {
+ "text" : "Deserializing user-controlled data may allow attackers to execute arbitrary code."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Deserialization of user-controlled data\nDeserializing untrusted data using any deserialization framework that allows the construction of arbitrary functions is easily exploitable and, in many cases, allows an attacker to execute arbitrary code.\n\n\n## Recommendation\nAvoid deserialization of untrusted data if at all possible. If the architecture permits it, then use formats like JSON or XML that cannot represent functions. When using YAML or other formats that support the serialization and deserialization of functions, ensure that the parser is configured to disable deserialization of arbitrary functions.\n\n\n## Example\nThe following example calls the `load` function of the popular `js-yaml` package on data that comes from an HTTP request and hence is inherently unsafe.\n\n\n```javascript\nconst app = require(\"express\")(),\n jsyaml = require(\"js-yaml\");\n\napp.get(\"load\", function(req, res) {\n let data = jsyaml.load(req.params.data);\n // ...\n});\n\n```\nUsing the `safeLoad` function instead (which does not deserialize YAML-encoded functions) removes the vulnerability.\n\n\n```javascript\nconst app = require(\"express\")(),\n jsyaml = require(\"js-yaml\");\n\napp.get(\"load\", function(req, res) {\n let data = jsyaml.safeLoad(req.params.data);\n // ...\n});\n\n```\n\n## References\n* OWASP vulnerability description: [Deserialization of untrusted data](https://www.owasp.org/index.php/Deserialization_of_untrusted_data).\n* OWASP guidance on deserializing objects: [Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html).\n* Neal Poole: [Code Execution via YAML in JS-YAML Node.js Module](https://nealpoole.com/blog/2013/06/code-execution-via-yaml-in-js-yaml-nodejs-module/).\n* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html).\n",
+ "markdown" : "# Deserialization of user-controlled data\nDeserializing untrusted data using any deserialization framework that allows the construction of arbitrary functions is easily exploitable and, in many cases, allows an attacker to execute arbitrary code.\n\n\n## Recommendation\nAvoid deserialization of untrusted data if at all possible. If the architecture permits it, then use formats like JSON or XML that cannot represent functions. When using YAML or other formats that support the serialization and deserialization of functions, ensure that the parser is configured to disable deserialization of arbitrary functions.\n\n\n## Example\nThe following example calls the `load` function of the popular `js-yaml` package on data that comes from an HTTP request and hence is inherently unsafe.\n\n\n```javascript\nconst app = require(\"express\")(),\n jsyaml = require(\"js-yaml\");\n\napp.get(\"load\", function(req, res) {\n let data = jsyaml.load(req.params.data);\n // ...\n});\n\n```\nUsing the `safeLoad` function instead (which does not deserialize YAML-encoded functions) removes the vulnerability.\n\n\n```javascript\nconst app = require(\"express\")(),\n jsyaml = require(\"js-yaml\");\n\napp.get(\"load\", function(req, res) {\n let data = jsyaml.safeLoad(req.params.data);\n // ...\n});\n\n```\n\n## References\n* OWASP vulnerability description: [Deserialization of untrusted data](https://www.owasp.org/index.php/Deserialization_of_untrusted_data).\n* OWASP guidance on deserializing objects: [Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html).\n* Neal Poole: [Code Execution via YAML in JS-YAML Node.js Module](https://nealpoole.com/blog/2013/06/code-execution-via-yaml-in-js-yaml-nodejs-module/).\n* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-502" ],
+ "description" : "Deserializing user-controlled data may allow attackers to\n execute arbitrary code.",
+ "id" : "js/unsafe-deserialization",
+ "kind" : "path-problem",
+ "name" : "Deserialization of user-controlled data",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "9.8"
+ }
+ }, {
+ "id" : "js/sensitive-get-query",
+ "name" : "js/sensitive-get-query",
+ "shortDescription" : {
+ "text" : "Sensitive data read from GET request"
+ },
+ "fullDescription" : {
+ "text" : "Placing sensitive data in a GET request increases the risk of the data being exposed to an attacker."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Sensitive data read from GET request\nSensitive information such as user passwords should not be transmitted within the query string of the requested URL. Sensitive information within URLs may be logged in various locations, including the user's browser, the web server, and any forward or reverse proxy servers between the two endpoints. URLs may also be displayed on-screen, bookmarked or emailed around by users. They may be disclosed to third parties via the Referer header when any off-site links are followed. Placing sensitive information into the URL therefore increases the risk that it will be captured by an attacker.\n\n\n## Recommendation\nUse HTTP POST to send sensitive information as part of the request body; for example, as form data.\n\n\n## Example\nThe following example shows two route handlers that both receive a username and a password. The first receives this sensitive information from the query parameters of a GET request, which is transmitted in the URL. The second receives this sensitive information from the request body of a POST request.\n\n\n```javascript\nconst express = require('express');\nconst app = express();\napp.use(require('body-parser').urlencoded({ extended: false }))\n\n// bad: sensitive information is read from query parameters\napp.get('/login1', (req, res) => {\n const user = req.query.user;\n const password = req.query.password;\n if (checkUser(user, password)) {\n res.send('Welcome');\n } else {\n res.send('Access denied');\n }\n});\n\n// good: sensitive information is read from post body\napp.post('/login2', (req, res) => {\n const user = req.body.user;\n const password = req.body.password;\n if (checkUser(user, password)) {\n res.send('Welcome');\n } else {\n res.send('Access denied');\n }\n});\n\n```\n\n## References\n* CWE: [CWE-598: Use of GET Request Method with Sensitive Query Strings](https://cwe.mitre.org/data/definitions/598.html)\n* PortSwigger (Burp): [Password Submitted using GET Method](https://portswigger.net/kb/issues/00400300_password-submitted-using-get-method)\n* OWASP: [Information Exposure through Query Strings in URL](https://owasp.org/www-community/vulnerabilities/Information_exposure_through_query_strings_in_url)\n* Common Weakness Enumeration: [CWE-598](https://cwe.mitre.org/data/definitions/598.html).\n",
+ "markdown" : "# Sensitive data read from GET request\nSensitive information such as user passwords should not be transmitted within the query string of the requested URL. Sensitive information within URLs may be logged in various locations, including the user's browser, the web server, and any forward or reverse proxy servers between the two endpoints. URLs may also be displayed on-screen, bookmarked or emailed around by users. They may be disclosed to third parties via the Referer header when any off-site links are followed. Placing sensitive information into the URL therefore increases the risk that it will be captured by an attacker.\n\n\n## Recommendation\nUse HTTP POST to send sensitive information as part of the request body; for example, as form data.\n\n\n## Example\nThe following example shows two route handlers that both receive a username and a password. The first receives this sensitive information from the query parameters of a GET request, which is transmitted in the URL. The second receives this sensitive information from the request body of a POST request.\n\n\n```javascript\nconst express = require('express');\nconst app = express();\napp.use(require('body-parser').urlencoded({ extended: false }))\n\n// bad: sensitive information is read from query parameters\napp.get('/login1', (req, res) => {\n const user = req.query.user;\n const password = req.query.password;\n if (checkUser(user, password)) {\n res.send('Welcome');\n } else {\n res.send('Access denied');\n }\n});\n\n// good: sensitive information is read from post body\napp.post('/login2', (req, res) => {\n const user = req.body.user;\n const password = req.body.password;\n if (checkUser(user, password)) {\n res.send('Welcome');\n } else {\n res.send('Access denied');\n }\n});\n\n```\n\n## References\n* CWE: [CWE-598: Use of GET Request Method with Sensitive Query Strings](https://cwe.mitre.org/data/definitions/598.html)\n* PortSwigger (Burp): [Password Submitted using GET Method](https://portswigger.net/kb/issues/00400300_password-submitted-using-get-method)\n* OWASP: [Information Exposure through Query Strings in URL](https://owasp.org/www-community/vulnerabilities/Information_exposure_through_query_strings_in_url)\n* Common Weakness Enumeration: [CWE-598](https://cwe.mitre.org/data/definitions/598.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-598" ],
+ "description" : "Placing sensitive data in a GET request increases the risk of\n the data being exposed to an attacker.",
+ "id" : "js/sensitive-get-query",
+ "kind" : "problem",
+ "name" : "Sensitive data read from GET request",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "6.5"
+ }
+ }, {
+ "id" : "js/cors-misconfiguration-for-credentials",
+ "name" : "js/cors-misconfiguration-for-credentials",
+ "shortDescription" : {
+ "text" : "CORS misconfiguration for credentials transfer"
+ },
+ "fullDescription" : {
+ "text" : "Misconfiguration of CORS HTTP headers allows for leaks of secret credentials."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# CORS misconfiguration for credentials transfer\nA server can send the `\"Access-Control-Allow-Credentials\"` CORS header to control when a browser may send user credentials in Cross-Origin HTTP requests.\n\nWhen the `Access-Control-Allow-Credentials` header is `\"true\"`, the `Access-Control-Allow-Origin` header must have a value different from `\"*\"` in order to make browsers accept the header. Therefore, to allow multiple origins for Cross-Origin requests with credentials, the server must dynamically compute the value of the `\"Access-Control-Allow-Origin\"` header. Computing this header value from information in the request to the server can therefore potentially allow an attacker to control the origins that the browser sends credentials to.\n\n\n## Recommendation\nWhen the `Access-Control-Allow-Credentials` header value is `\"true\"`, a dynamic computation of the `Access-Control-Allow-Origin` header must involve sanitization if it relies on user-controlled input.\n\nSince the `\"null\"` origin is easy to obtain for an attacker, it is never safe to use `\"null\"` as the value of the `Access-Control-Allow-Origin` header when the `Access-Control-Allow-Credentials` header value is `\"true\"`.\n\n\n## Example\nIn the example below, the server allows the browser to send user credentials in a Cross-Origin request. The request header `origins` controls the allowed origins for such a Cross-Origin request.\n\n\n```javascript\nvar https = require('https'),\n url = require('url');\n\nvar server = https.createServer(function(){});\n\nserver.on('request', function(req, res) {\n let origin = url.parse(req.url, true).query.origin;\n // BAD: attacker can choose the value of origin\n res.setHeader(\"Access-Control-Allow-Origin\", origin);\n res.setHeader(\"Access-Control-Allow-Credentials\", true);\n\n // ...\n});\n\n```\nThis is not secure, since an attacker can choose the value of the `origin` request header to make the browser send credentials to their own server. The use of a whitelist containing allowed origins for the Cross-Origin request fixes the issue:\n\n\n```javascript\nvar https = require('https'),\n url = require('url');\n\nvar server = https.createServer(function(){});\n\nserver.on('request', function(req, res) {\n let origin = url.parse(req.url, true).query.origin,\n whitelist = {\n \"https://example.com\": true,\n \"https://subdomain.example.com\": true,\n \"https://example.com:1337\": true\n };\n\n if (origin in whitelist) {\n // GOOD: the origin is in the whitelist\n res.setHeader(\"Access-Control-Allow-Origin\", origin);\n res.setHeader(\"Access-Control-Allow-Credentials\", true);\n }\n\n // ...\n});\n\n```\n\n## References\n* Mozilla Developer Network: [CORS, Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin).\n* Mozilla Developer Network: [CORS, Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials).\n* PortSwigger: [Exploiting CORS Misconfigurations for Bitcoins and Bounties](http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html)\n* W3C: [CORS for developers, Advice for Resource Owners](https://w3c.github.io/webappsec-cors-for-developers/#resources)\n* Common Weakness Enumeration: [CWE-346](https://cwe.mitre.org/data/definitions/346.html).\n* Common Weakness Enumeration: [CWE-639](https://cwe.mitre.org/data/definitions/639.html).\n* Common Weakness Enumeration: [CWE-942](https://cwe.mitre.org/data/definitions/942.html).\n",
+ "markdown" : "# CORS misconfiguration for credentials transfer\nA server can send the `\"Access-Control-Allow-Credentials\"` CORS header to control when a browser may send user credentials in Cross-Origin HTTP requests.\n\nWhen the `Access-Control-Allow-Credentials` header is `\"true\"`, the `Access-Control-Allow-Origin` header must have a value different from `\"*\"` in order to make browsers accept the header. Therefore, to allow multiple origins for Cross-Origin requests with credentials, the server must dynamically compute the value of the `\"Access-Control-Allow-Origin\"` header. Computing this header value from information in the request to the server can therefore potentially allow an attacker to control the origins that the browser sends credentials to.\n\n\n## Recommendation\nWhen the `Access-Control-Allow-Credentials` header value is `\"true\"`, a dynamic computation of the `Access-Control-Allow-Origin` header must involve sanitization if it relies on user-controlled input.\n\nSince the `\"null\"` origin is easy to obtain for an attacker, it is never safe to use `\"null\"` as the value of the `Access-Control-Allow-Origin` header when the `Access-Control-Allow-Credentials` header value is `\"true\"`.\n\n\n## Example\nIn the example below, the server allows the browser to send user credentials in a Cross-Origin request. The request header `origins` controls the allowed origins for such a Cross-Origin request.\n\n\n```javascript\nvar https = require('https'),\n url = require('url');\n\nvar server = https.createServer(function(){});\n\nserver.on('request', function(req, res) {\n let origin = url.parse(req.url, true).query.origin;\n // BAD: attacker can choose the value of origin\n res.setHeader(\"Access-Control-Allow-Origin\", origin);\n res.setHeader(\"Access-Control-Allow-Credentials\", true);\n\n // ...\n});\n\n```\nThis is not secure, since an attacker can choose the value of the `origin` request header to make the browser send credentials to their own server. The use of a whitelist containing allowed origins for the Cross-Origin request fixes the issue:\n\n\n```javascript\nvar https = require('https'),\n url = require('url');\n\nvar server = https.createServer(function(){});\n\nserver.on('request', function(req, res) {\n let origin = url.parse(req.url, true).query.origin,\n whitelist = {\n \"https://example.com\": true,\n \"https://subdomain.example.com\": true,\n \"https://example.com:1337\": true\n };\n\n if (origin in whitelist) {\n // GOOD: the origin is in the whitelist\n res.setHeader(\"Access-Control-Allow-Origin\", origin);\n res.setHeader(\"Access-Control-Allow-Credentials\", true);\n }\n\n // ...\n});\n\n```\n\n## References\n* Mozilla Developer Network: [CORS, Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin).\n* Mozilla Developer Network: [CORS, Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials).\n* PortSwigger: [Exploiting CORS Misconfigurations for Bitcoins and Bounties](http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html)\n* W3C: [CORS for developers, Advice for Resource Owners](https://w3c.github.io/webappsec-cors-for-developers/#resources)\n* Common Weakness Enumeration: [CWE-346](https://cwe.mitre.org/data/definitions/346.html).\n* Common Weakness Enumeration: [CWE-639](https://cwe.mitre.org/data/definitions/639.html).\n* Common Weakness Enumeration: [CWE-942](https://cwe.mitre.org/data/definitions/942.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-346", "external/cwe/cwe-639", "external/cwe/cwe-942" ],
+ "description" : "Misconfiguration of CORS HTTP headers allows for leaks of secret credentials.",
+ "id" : "js/cors-misconfiguration-for-credentials",
+ "kind" : "path-problem",
+ "name" : "CORS misconfiguration for credentials transfer",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "7.5"
+ }
+ }, {
+ "id" : "js/cross-window-information-leak",
+ "name" : "js/cross-window-information-leak",
+ "shortDescription" : {
+ "text" : "Cross-window communication with unrestricted target origin"
+ },
+ "fullDescription" : {
+ "text" : "When sending sensitive information to another window using `postMessage`, the origin of the target window should be restricted to avoid unintentional information leaks."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Cross-window communication with unrestricted target origin\nThe `window.postMessage` method allows different windows or iframes to communicate directly, even if they were loaded from different origins, circumventing the usual same-origin policy.\n\nThe sender of the message can restrict the origin of the receiver by specifying a target origin. If the receiver window does not come from this origin, the message is not sent.\n\nAlternatively, the sender can specify a target origin of `'*'`, which means that any origin is acceptable and the message is always sent.\n\nThis feature should not be used if the message being sent contains sensitive data such as user credentials: the target window may have been loaded from a malicious site, to which the data would then become available.\n\n\n## Recommendation\nIf possible, specify a target origin when using `window.postMessage`. Alternatively, encrypt the sensitive data before sending it to prevent an unauthorized receiver from accessing it.\n\n\n## Example\nThe following example code sends user credentials (in this case, their user name) to `window.parent` without checking its origin. If a malicious site loads the page containing this code into an iframe it would be able to gain access to the user name.\n\n\n```javascript\nwindow.parent.postMessage(userName, '*');\n\n```\nTo prevent this from happening, the origin of the target window should be restricted, as in this example:\n\n\n```javascript\nwindow.parent.postMessage(userName, 'https://github.com');\n\n```\n\n## References\n* Mozilla Developer Network: [Window.postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage).\n* Mozilla Developer Network: [Same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy).\n* Common Weakness Enumeration: [CWE-201](https://cwe.mitre.org/data/definitions/201.html).\n* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html).\n",
+ "markdown" : "# Cross-window communication with unrestricted target origin\nThe `window.postMessage` method allows different windows or iframes to communicate directly, even if they were loaded from different origins, circumventing the usual same-origin policy.\n\nThe sender of the message can restrict the origin of the receiver by specifying a target origin. If the receiver window does not come from this origin, the message is not sent.\n\nAlternatively, the sender can specify a target origin of `'*'`, which means that any origin is acceptable and the message is always sent.\n\nThis feature should not be used if the message being sent contains sensitive data such as user credentials: the target window may have been loaded from a malicious site, to which the data would then become available.\n\n\n## Recommendation\nIf possible, specify a target origin when using `window.postMessage`. Alternatively, encrypt the sensitive data before sending it to prevent an unauthorized receiver from accessing it.\n\n\n## Example\nThe following example code sends user credentials (in this case, their user name) to `window.parent` without checking its origin. If a malicious site loads the page containing this code into an iframe it would be able to gain access to the user name.\n\n\n```javascript\nwindow.parent.postMessage(userName, '*');\n\n```\nTo prevent this from happening, the origin of the target window should be restricted, as in this example:\n\n\n```javascript\nwindow.parent.postMessage(userName, 'https://github.com');\n\n```\n\n## References\n* Mozilla Developer Network: [Window.postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage).\n* Mozilla Developer Network: [Same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy).\n* Common Weakness Enumeration: [CWE-201](https://cwe.mitre.org/data/definitions/201.html).\n* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-201", "external/cwe/cwe-359" ],
+ "description" : "When sending sensitive information to another window using `postMessage`,\n the origin of the target window should be restricted to avoid unintentional\n information leaks.",
+ "id" : "js/cross-window-information-leak",
+ "kind" : "path-problem",
+ "name" : "Cross-window communication with unrestricted target origin",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "4.3"
+ }
+ }, {
+ "id" : "js/xss",
+ "name" : "js/xss",
+ "shortDescription" : {
+ "text" : "Client-side cross-site scripting"
+ },
+ "fullDescription" : {
+ "text" : "Writing user input directly to the DOM allows for a cross-site scripting vulnerability."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Client-side cross-site scripting\nDirectly writing user input (for example, a URL query parameter) to a webpage without properly sanitizing the input first, allows for a cross-site scripting vulnerability.\n\nThis kind of vulnerability is also called *DOM-based* cross-site scripting, to distinguish it from other types of cross-site scripting.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references.\n\n\n## Example\nThe following example shows part of the page URL being written directly to the document, leaving the website vulnerable to cross-site scripting.\n\n\n```javascript\nfunction setLanguageOptions() {\n var href = document.location.href,\n deflt = href.substring(href.indexOf(\"default=\")+8);\n document.write(\"\");\n document.write(\"\");\n}\n\n```\n\n## References\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 [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/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" : "# Client-side cross-site scripting\nDirectly writing user input (for example, a URL query parameter) to a webpage without properly sanitizing the input first, allows for a cross-site scripting vulnerability.\n\nThis kind of vulnerability is also called *DOM-based* cross-site scripting, to distinguish it from other types of cross-site scripting.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references.\n\n\n## Example\nThe following example shows part of the page URL being written directly to the document, leaving the website vulnerable to cross-site scripting.\n\n\n```javascript\nfunction setLanguageOptions() {\n var href = document.location.href,\n deflt = href.substring(href.indexOf(\"default=\")+8);\n document.write(\"\");\n document.write(\"\");\n}\n\n```\n\n## References\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 [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/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" : [ "security", "external/cwe/cwe-079", "external/cwe/cwe-116" ],
+ "description" : "Writing user input directly to the DOM allows for\n a cross-site scripting vulnerability.",
+ "id" : "js/xss",
+ "kind" : "path-problem",
+ "name" : "Client-side cross-site scripting",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "7.8"
+ }
+ }, {
+ "id" : "js/xss-through-dom",
+ "name" : "js/xss-through-dom",
+ "shortDescription" : {
+ "text" : "DOM text reinterpreted as HTML"
+ },
+ "fullDescription" : {
+ "text" : "Reinterpreting text from the DOM as HTML can lead to a cross-site scripting vulnerability."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# DOM text reinterpreted as HTML\nExtracting text from a DOM node and interpreting it as HTML can lead to a cross-site scripting vulnerability.\n\nA webpage with this vulnerability reads text from the DOM, and afterwards adds the text as HTML to the DOM. Using text from the DOM as HTML effectively unescapes the text, and thereby invalidates any escaping done on the text. If an attacker is able to control the safe sanitized text, then this vulnerability can be exploited to perform a cross-site scripting attack.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before writing text to the page, or one of the other solutions that are mentioned in the References section below.\n\n\n## Example\nThe following example shows a webpage using a `data-target` attribute to select and manipulate a DOM element using the JQuery library. In the example, the `data-target` attribute is read into the `target` variable, and the `$` function is then supposed to use the `target` variable as a CSS selector to determine which element should be manipulated.\n\n\n```javascript\n$(\"button\").click(function () {\n var target = $(this).attr(\"data-target\");\n $(target).hide();\n});\n\n```\nHowever, if an attacker can control the `data-target` attribute, then the value of `target` can be used to cause the `$` function to execute arbitrary JavaScript.\n\nThe above vulnerability can be fixed by using `$.find` instead of `$`. The `$.find` function will only interpret `target` as a CSS selector and never as HTML, thereby preventing an XSS attack.\n\n\n```javascript\n$(\"button\").click(function () {\n var target = $(this).attr(\"data-target\");\n\t$.find(target).hide();\n});\n\n```\n\n## References\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 [DOM Based XSS](https://owasp.org/www-community/attacks/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](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" : "# DOM text reinterpreted as HTML\nExtracting text from a DOM node and interpreting it as HTML can lead to a cross-site scripting vulnerability.\n\nA webpage with this vulnerability reads text from the DOM, and afterwards adds the text as HTML to the DOM. Using text from the DOM as HTML effectively unescapes the text, and thereby invalidates any escaping done on the text. If an attacker is able to control the safe sanitized text, then this vulnerability can be exploited to perform a cross-site scripting attack.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before writing text to the page, or one of the other solutions that are mentioned in the References section below.\n\n\n## Example\nThe following example shows a webpage using a `data-target` attribute to select and manipulate a DOM element using the JQuery library. In the example, the `data-target` attribute is read into the `target` variable, and the `$` function is then supposed to use the `target` variable as a CSS selector to determine which element should be manipulated.\n\n\n```javascript\n$(\"button\").click(function () {\n var target = $(this).attr(\"data-target\");\n $(target).hide();\n});\n\n```\nHowever, if an attacker can control the `data-target` attribute, then the value of `target` can be used to cause the `$` function to execute arbitrary JavaScript.\n\nThe above vulnerability can be fixed by using `$.find` instead of `$`. The `$.find` function will only interpret `target` as a CSS selector and never as HTML, thereby preventing an XSS attack.\n\n\n```javascript\n$(\"button\").click(function () {\n var target = $(this).attr(\"data-target\");\n\t$.find(target).hide();\n});\n\n```\n\n## References\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 [DOM Based XSS](https://owasp.org/www-community/attacks/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](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" : [ "security", "external/cwe/cwe-079", "external/cwe/cwe-116" ],
+ "description" : "Reinterpreting text from the DOM as HTML\n can lead to a cross-site scripting vulnerability.",
+ "id" : "js/xss-through-dom",
+ "kind" : "path-problem",
+ "name" : "DOM text reinterpreted as HTML",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "6.1"
+ }
+ }, {
+ "id" : "js/stored-xss",
+ "name" : "js/stored-xss",
+ "shortDescription" : {
+ "text" : "Stored cross-site scripting"
+ },
+ "fullDescription" : {
+ "text" : "Using uncontrolled stored values in HTML allows for a stored cross-site scripting vulnerability."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Stored cross-site scripting\nDirectly using uncontrolled stored value (for example, file names) to create HTML content without properly sanitizing the input first, allows for a cross-site scripting vulnerability.\n\nThis kind of vulnerability is also called *stored* cross-site scripting, to distinguish it from other types of cross-site scripting.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before using uncontrolled stored values to create HTML content, or one of the other solutions that are mentioned in the references.\n\n\n## Example\nThe following example code writes file names directly to a HTTP response. This leaves the website vulnerable to cross-site scripting, if an attacker can choose the file names on the disk.\n\n\n```javascript\nvar express = require('express'),\n fs = require('fs');\n\nexpress().get('/list-directory', function(req, res) {\n fs.readdir('/public', function (error, fileNames) {\n var list = '
';\n fileNames.forEach(fileName => {\n // BAD: `fileName` can contain HTML elements\n list += '
' + fileName + '
';\n });\n list += '
'\n res.send(list);\n });\n});\n\n```\nSanitizing the file names prevents the vulnerability:\n\n\n```javascript\nvar express = require('express'),\n fs = require('fs'),\n escape = require('escape-html');\n\nexpress().get('/list-directory', function(req, res) {\n fs.readdir('/public', function (error, fileNames) {\n var list = '
';\n fileNames.forEach(fileName => {\n // GOOD: escaped `fileName` can not contain HTML elements\n list += '
' + escape(fileName) + '
';\n });\n list += '
'\n res.send(list);\n });\n});\n\n```\n\n## References\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 Scripting](https://www.owasp.org/index.php/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" : "# Stored cross-site scripting\nDirectly using uncontrolled stored value (for example, file names) to create HTML content without properly sanitizing the input first, allows for a cross-site scripting vulnerability.\n\nThis kind of vulnerability is also called *stored* cross-site scripting, to distinguish it from other types of cross-site scripting.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before using uncontrolled stored values to create HTML content, or one of the other solutions that are mentioned in the references.\n\n\n## Example\nThe following example code writes file names directly to a HTTP response. This leaves the website vulnerable to cross-site scripting, if an attacker can choose the file names on the disk.\n\n\n```javascript\nvar express = require('express'),\n fs = require('fs');\n\nexpress().get('/list-directory', function(req, res) {\n fs.readdir('/public', function (error, fileNames) {\n var list = '
';\n fileNames.forEach(fileName => {\n // BAD: `fileName` can contain HTML elements\n list += '
' + fileName + '
';\n });\n list += '
'\n res.send(list);\n });\n});\n\n```\nSanitizing the file names prevents the vulnerability:\n\n\n```javascript\nvar express = require('express'),\n fs = require('fs'),\n escape = require('escape-html');\n\nexpress().get('/list-directory', function(req, res) {\n fs.readdir('/public', function (error, fileNames) {\n var list = '
';\n fileNames.forEach(fileName => {\n // GOOD: escaped `fileName` can not contain HTML elements\n list += '
' + escape(fileName) + '
';\n });\n list += '
'\n res.send(list);\n });\n});\n\n```\n\n## References\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 Scripting](https://www.owasp.org/index.php/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" : [ "security", "external/cwe/cwe-079", "external/cwe/cwe-116" ],
+ "description" : "Using uncontrolled stored values in HTML allows for\n a stored cross-site scripting vulnerability.",
+ "id" : "js/stored-xss",
+ "kind" : "path-problem",
+ "name" : "Stored cross-site scripting",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "7.8"
+ }
+ }, {
+ "id" : "js/reflected-xss",
+ "name" : "js/reflected-xss",
+ "shortDescription" : {
+ "text" : "Reflected cross-site scripting"
+ },
+ "fullDescription" : {
+ "text" : "Writing user input directly to an HTTP response allows for a cross-site scripting vulnerability."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Reflected cross-site scripting\nDirectly writing user input (for example, an HTTP request parameter) to an HTTP response without properly sanitizing the input first, allows for a cross-site scripting vulnerability.\n\nThis kind of vulnerability is also called *reflected* cross-site scripting, to distinguish it from other types of cross-site scripting.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the response, or one of the other solutions that are mentioned in the references.\n\n\n## Example\nThe following example code writes part of an HTTP request (which is controlled by the user) directly to the response. This leaves the website vulnerable to cross-site scripting.\n\n\n```javascript\nvar app = require('express')();\n\napp.get('/user/:id', function(req, res) {\n if (!isValidUserId(req.params.id))\n // BAD: a request parameter is incorporated without validation into the response\n res.send(\"Unknown user: \" + req.params.id);\n else\n // TODO: do something exciting\n ;\n});\n\n```\nSanitizing the user-controlled data prevents the vulnerability:\n\n\n```javascript\nvar escape = require('escape-html');\n\nvar app = require('express')();\n\napp.get('/user/:id', function(req, res) {\n if (!isValidUserId(req.params.id))\n // GOOD: request parameter is sanitized before incorporating it into the response\n res.send(\"Unknown user: \" + escape(req.params.id));\n else\n // TODO: do something exciting\n ;\n});\n\n```\n\n## References\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 Scripting](https://www.owasp.org/index.php/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" : "# Reflected cross-site scripting\nDirectly writing user input (for example, an HTTP request parameter) to an HTTP response without properly sanitizing the input first, allows for a cross-site scripting vulnerability.\n\nThis kind of vulnerability is also called *reflected* cross-site scripting, to distinguish it from other types of cross-site scripting.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the response, or one of the other solutions that are mentioned in the references.\n\n\n## Example\nThe following example code writes part of an HTTP request (which is controlled by the user) directly to the response. This leaves the website vulnerable to cross-site scripting.\n\n\n```javascript\nvar app = require('express')();\n\napp.get('/user/:id', function(req, res) {\n if (!isValidUserId(req.params.id))\n // BAD: a request parameter is incorporated without validation into the response\n res.send(\"Unknown user: \" + req.params.id);\n else\n // TODO: do something exciting\n ;\n});\n\n```\nSanitizing the user-controlled data prevents the vulnerability:\n\n\n```javascript\nvar escape = require('escape-html');\n\nvar app = require('express')();\n\napp.get('/user/:id', function(req, res) {\n if (!isValidUserId(req.params.id))\n // GOOD: request parameter is sanitized before incorporating it into the response\n res.send(\"Unknown user: \" + escape(req.params.id));\n else\n // TODO: do something exciting\n ;\n});\n\n```\n\n## References\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 Scripting](https://www.owasp.org/index.php/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" : [ "security", "external/cwe/cwe-079", "external/cwe/cwe-116" ],
+ "description" : "Writing user input directly to an HTTP response allows for\n a cross-site scripting vulnerability.",
+ "id" : "js/reflected-xss",
+ "kind" : "path-problem",
+ "name" : "Reflected cross-site scripting",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "7.8"
+ }
+ }, {
+ "id" : "js/html-constructed-from-input",
+ "name" : "js/html-constructed-from-input",
+ "shortDescription" : {
+ "text" : "Unsafe HTML constructed from library input"
+ },
+ "fullDescription" : {
+ "text" : "Using externally controlled strings to construct HTML might allow a malicious user to perform a cross-site scripting attack."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "error"
+ },
+ "help" : {
+ "text" : "# Unsafe HTML constructed from library input\nWhen a library function dynamically constructs HTML in a potentially unsafe way, then it's important to document to clients of the library that the function should only be used with trusted inputs. If the function is not documented as being potentially unsafe, then a client may inadvertently use inputs containing unsafe HTML fragments, and thereby leave the client vulnerable to cross-site scripting attacks.\n\n\n## Recommendation\nDocument all library functions that can lead to cross-site scripting attacks, and guard against unsafe inputs where dynamic HTML construction is not intended.\n\n\n## Example\nThe following example has a library function that renders a boldface name by writing to the `innerHTML` property of an element.\n\n\n```javascript\nmodule.exports = function showBoldName(name) {\n document.getElementById('name').innerHTML = \"\" + name + \"\";\n}\n\n```\nThis library function, however, does not escape unsafe HTML, and a client that calls the function with user-supplied input may be vulnerable to cross-site scripting attacks.\n\nThe library could either document that this function should not be used with unsafe inputs, or use safe APIs such as `innerText`.\n\n\n```javascript\nmodule.exports = function showBoldName(name) {\n const bold = document.createElement('b');\n bold.innerText = name;\n document.getElementById('name').appendChild(bold);\n}\n\n```\nAlternatively, an HTML sanitizer can be used to remove unsafe content.\n\n\n```javascript\n\nconst striptags = require('striptags');\nmodule.exports = function showBoldName(name) {\n document.getElementById('name').innerHTML = \"\" + striptags(name) + \"\";\n}\n\n```\n\n## References\n* OWASP: [DOM based XSS Prevention Cheat Sheet](https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet).\n* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet).\n* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/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 HTML constructed from library input\nWhen a library function dynamically constructs HTML in a potentially unsafe way, then it's important to document to clients of the library that the function should only be used with trusted inputs. If the function is not documented as being potentially unsafe, then a client may inadvertently use inputs containing unsafe HTML fragments, and thereby leave the client vulnerable to cross-site scripting attacks.\n\n\n## Recommendation\nDocument all library functions that can lead to cross-site scripting attacks, and guard against unsafe inputs where dynamic HTML construction is not intended.\n\n\n## Example\nThe following example has a library function that renders a boldface name by writing to the `innerHTML` property of an element.\n\n\n```javascript\nmodule.exports = function showBoldName(name) {\n document.getElementById('name').innerHTML = \"\" + name + \"\";\n}\n\n```\nThis library function, however, does not escape unsafe HTML, and a client that calls the function with user-supplied input may be vulnerable to cross-site scripting attacks.\n\nThe library could either document that this function should not be used with unsafe inputs, or use safe APIs such as `innerText`.\n\n\n```javascript\nmodule.exports = function showBoldName(name) {\n const bold = document.createElement('b');\n bold.innerText = name;\n document.getElementById('name').appendChild(bold);\n}\n\n```\nAlternatively, an HTML sanitizer can be used to remove unsafe content.\n\n\n```javascript\n\nconst striptags = require('striptags');\nmodule.exports = function showBoldName(name) {\n document.getElementById('name').innerHTML = \"\" + striptags(name) + \"\";\n}\n\n```\n\n## References\n* OWASP: [DOM based XSS Prevention Cheat Sheet](https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet).\n* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet).\n* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/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" : [ "security", "external/cwe/cwe-079", "external/cwe/cwe-116" ],
+ "description" : "Using externally controlled strings to construct HTML might allow a malicious\n user to perform a cross-site scripting attack.",
+ "id" : "js/html-constructed-from-input",
+ "kind" : "path-problem",
+ "name" : "Unsafe HTML constructed from library input",
+ "precision" : "high",
+ "problem.severity" : "error",
+ "security-severity" : "6.1"
+ }
+ }, {
+ "id" : "js/xss-through-exception",
+ "name" : "js/xss-through-exception",
+ "shortDescription" : {
+ "text" : "Exception text reinterpreted as HTML"
+ },
+ "fullDescription" : {
+ "text" : "Reinterpreting text from an exception as HTML can lead to a cross-site scripting vulnerability."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Exception text reinterpreted as HTML\nDirectly writing error messages to a webpage without sanitization allows for a cross-site scripting vulnerability if parts of the error message can be influenced by a user.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references.\n\n\n## Example\nThe following example shows an exception being written directly to the document, and this exception can potentially be influenced by the page URL, leaving the website vulnerable to cross-site scripting.\n\n\n```javascript\nfunction setLanguageOptions() {\n var href = document.location.href,\n deflt = href.substring(href.indexOf(\"default=\")+8);\n \n try {\n var parsed = unknownParseFunction(deflt); \n } catch(e) {\n document.write(\"Had an error: \" + e + \".\");\n }\n}\n\n```\n\n## Example\nThis second example shows an input being validated using the JSON schema validator `ajv`, and in case of an error, the error message is sent directly back in the response.\n\n\n```javascript\nimport express from 'express';\nimport Ajv from 'ajv';\n\nlet app = express();\nlet ajv = new Ajv();\n\najv.addSchema({type: 'object', additionalProperties: {type: 'number'}}, 'pollData');\n\napp.post('/polldata', (req, res) => {\n if (!ajv.validate('pollData', req.body)) {\n res.send(ajv.errorsText());\n }\n});\n\n```\nThis is unsafe, because the error message can contain parts of the input. For example, the input `{'': 'foo'}` will generate the error `data/ should be number`, causing reflected XSS.\n\n\n## References\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 [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/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" : "# Exception text reinterpreted as HTML\nDirectly writing error messages to a webpage without sanitization allows for a cross-site scripting vulnerability if parts of the error message can be influenced by a user.\n\n\n## Recommendation\nTo guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references.\n\n\n## Example\nThe following example shows an exception being written directly to the document, and this exception can potentially be influenced by the page URL, leaving the website vulnerable to cross-site scripting.\n\n\n```javascript\nfunction setLanguageOptions() {\n var href = document.location.href,\n deflt = href.substring(href.indexOf(\"default=\")+8);\n \n try {\n var parsed = unknownParseFunction(deflt); \n } catch(e) {\n document.write(\"Had an error: \" + e + \".\");\n }\n}\n\n```\n\n## Example\nThis second example shows an input being validated using the JSON schema validator `ajv`, and in case of an error, the error message is sent directly back in the response.\n\n\n```javascript\nimport express from 'express';\nimport Ajv from 'ajv';\n\nlet app = express();\nlet ajv = new Ajv();\n\najv.addSchema({type: 'object', additionalProperties: {type: 'number'}}, 'pollData');\n\napp.post('/polldata', (req, res) => {\n if (!ajv.validate('pollData', req.body)) {\n res.send(ajv.errorsText());\n }\n});\n\n```\nThis is unsafe, because the error message can contain parts of the input. For example, the input `{'': 'foo'}` will generate the error `data/ should be number`, causing reflected XSS.\n\n\n## References\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 [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/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" : [ "security", "external/cwe/cwe-079", "external/cwe/cwe-116" ],
+ "description" : "Reinterpreting text from an exception as HTML\n can lead to a cross-site scripting vulnerability.",
+ "id" : "js/xss-through-exception",
+ "kind" : "path-problem",
+ "name" : "Exception text reinterpreted as HTML",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "6.1"
+ }
+ }, {
+ "id" : "js/unsafe-jquery-plugin",
+ "name" : "js/unsafe-jquery-plugin",
+ "shortDescription" : {
+ "text" : "Unsafe jQuery plugin"
+ },
+ "fullDescription" : {
+ "text" : "A jQuery plugin that unintentionally constructs HTML from some of its options may be unsafe to use for clients."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Unsafe jQuery plugin\nLibrary plugins, such as those for the jQuery library, are often configurable through options provided by the clients of the plugin. Clients, however, do not know the implementation details of the plugin, so it is important to document the capabilities of each option. The documentation for the plugin options that the client is responsible for sanitizing is of particular importance. Otherwise, the plugin may write user input (for example, a URL query parameter) to a web page without properly sanitizing it first, which allows for a cross-site scripting vulnerability in the client application through dynamic HTML construction.\n\n\n## Recommendation\nDocument all options that can lead to cross-site scripting attacks, and guard against unsafe inputs where dynamic HTML construction is not intended.\n\n\n## Example\nThe following example shows a jQuery plugin that selects a DOM element, and copies its text content to another DOM element. The selection is performed by using the plugin option `sourceSelector` as a CSS selector.\n\n\n```javascript\njQuery.fn.copyText = function(options) {\n\t// BAD may evaluate `options.sourceSelector` as HTML\n\tvar source = jQuery(options.sourceSelector),\n\t text = source.text();\n\tjQuery(this).text(text);\n}\n\n```\nThis is, however, not a safe plugin, since the call to `jQuery` interprets `sourceSelector` as HTML if it is a string that starts with `<`.\n\nInstead of documenting that the client is responsible for sanitizing `sourceSelector`, the plugin can use `jQuery.find` to always interpret `sourceSelector` as a CSS selector:\n\n\n```javascript\njQuery.fn.copyText = function(options) {\n\t// GOOD may not evaluate `options.sourceSelector` as HTML\n\tvar source = jQuery.find(options.sourceSelector),\n\t text = source.text();\n\tjQuery(this).text(text);\n}\n\n```\n\n## References\n* OWASP: [DOM based XSS Prevention Cheat Sheet](https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet).\n* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).\n* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting).\n* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting).\n* jQuery: [Plugin creation](https://learn.jquery.com/plugins/basic-plugin-creation/).\n* Bootstrap: [XSS vulnerable bootstrap plugins](https://github.com/twbs/bootstrap/pull/27047).\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 jQuery plugin\nLibrary plugins, such as those for the jQuery library, are often configurable through options provided by the clients of the plugin. Clients, however, do not know the implementation details of the plugin, so it is important to document the capabilities of each option. The documentation for the plugin options that the client is responsible for sanitizing is of particular importance. Otherwise, the plugin may write user input (for example, a URL query parameter) to a web page without properly sanitizing it first, which allows for a cross-site scripting vulnerability in the client application through dynamic HTML construction.\n\n\n## Recommendation\nDocument all options that can lead to cross-site scripting attacks, and guard against unsafe inputs where dynamic HTML construction is not intended.\n\n\n## Example\nThe following example shows a jQuery plugin that selects a DOM element, and copies its text content to another DOM element. The selection is performed by using the plugin option `sourceSelector` as a CSS selector.\n\n\n```javascript\njQuery.fn.copyText = function(options) {\n\t// BAD may evaluate `options.sourceSelector` as HTML\n\tvar source = jQuery(options.sourceSelector),\n\t text = source.text();\n\tjQuery(this).text(text);\n}\n\n```\nThis is, however, not a safe plugin, since the call to `jQuery` interprets `sourceSelector` as HTML if it is a string that starts with `<`.\n\nInstead of documenting that the client is responsible for sanitizing `sourceSelector`, the plugin can use `jQuery.find` to always interpret `sourceSelector` as a CSS selector:\n\n\n```javascript\njQuery.fn.copyText = function(options) {\n\t// GOOD may not evaluate `options.sourceSelector` as HTML\n\tvar source = jQuery.find(options.sourceSelector),\n\t text = source.text();\n\tjQuery(this).text(text);\n}\n\n```\n\n## References\n* OWASP: [DOM based XSS Prevention Cheat Sheet](https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet).\n* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).\n* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS).\n* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting).\n* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting).\n* jQuery: [Plugin creation](https://learn.jquery.com/plugins/basic-plugin-creation/).\n* Bootstrap: [XSS vulnerable bootstrap plugins](https://github.com/twbs/bootstrap/pull/27047).\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" : [ "security", "external/cwe/cwe-079", "external/cwe/cwe-116", "frameworks/jquery" ],
+ "description" : "A jQuery plugin that unintentionally constructs HTML from some of its options may be unsafe to use for clients.",
+ "id" : "js/unsafe-jquery-plugin",
+ "kind" : "path-problem",
+ "name" : "Unsafe jQuery plugin",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "6.1"
+ }
+ }, {
+ "id" : "js/incomplete-html-attribute-sanitization",
+ "name" : "js/incomplete-html-attribute-sanitization",
+ "shortDescription" : {
+ "text" : "Incomplete HTML attribute sanitization"
+ },
+ "fullDescription" : {
+ "text" : "Writing incompletely sanitized values to HTML attribute strings can lead to a cross-site scripting vulnerability."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "help" : {
+ "text" : "# Incomplete HTML attribute sanitization\nSanitizing untrusted input for HTML meta-characters is a common technique for preventing cross-site scripting attacks. Usually, this is done by escaping `<`, `>`, `&` and `\"`. However, the context in which the sanitized value is used decides the characters that need to be sanitized.\n\nAs a consequence, some programs only sanitize `<` and `>` since those are the most common dangerous characters. The lack of sanitization for `\"` is problematic when an incompletely sanitized value is used as an HTML attribute in a string that later is parsed as HTML.\n\n\n## Recommendation\nSanitize all relevant HTML meta-characters when constructing HTML dynamically, and pay special attention to where the sanitized value is used.\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 example code writes part of an HTTP request (which is controlled by the user) to an HTML attribute of the server response. The user-controlled value is, however, not sanitized for `\"`. This leaves the website vulnerable to cross-site scripting since an attacker can use a string like `\" onclick=\"alert(42)` to inject JavaScript code into the response.\n\n\n```javascript\nvar app = require('express')();\n\napp.get('/user/:id', function(req, res) {\n\tlet id = req.params.id;\n\tid = id.replace(/<|>/g, \"\"); // BAD\n\tlet userHtml = `
${getUserName(id) || \"Unknown name\"}
`;\n\t// ...\n\tres.send(prefix + userHtml + suffix);\n});\n\n```\nSanitizing the user-controlled data for `\"` helps prevent the vulnerability:\n\n\n```javascript\nvar app = require('express')();\n\napp.get('/user/:id', function(req, res) {\n\tlet id = req.params.id;\n\tid = id.replace(/<|>|&|\"/g, \"\"); // GOOD\n\tlet userHtml = `
${getUserName(id) || \"Unknown name\"}
`;\n\t// ...\n\tres.send(prefix + userHtml + suffix);\n});\n\n```\n\n## References\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* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n",
+ "markdown" : "# Incomplete HTML attribute sanitization\nSanitizing untrusted input for HTML meta-characters is a common technique for preventing cross-site scripting attacks. Usually, this is done by escaping `<`, `>`, `&` and `\"`. However, the context in which the sanitized value is used decides the characters that need to be sanitized.\n\nAs a consequence, some programs only sanitize `<` and `>` since those are the most common dangerous characters. The lack of sanitization for `\"` is problematic when an incompletely sanitized value is used as an HTML attribute in a string that later is parsed as HTML.\n\n\n## Recommendation\nSanitize all relevant HTML meta-characters when constructing HTML dynamically, and pay special attention to where the sanitized value is used.\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 example code writes part of an HTTP request (which is controlled by the user) to an HTML attribute of the server response. The user-controlled value is, however, not sanitized for `\"`. This leaves the website vulnerable to cross-site scripting since an attacker can use a string like `\" onclick=\"alert(42)` to inject JavaScript code into the response.\n\n\n```javascript\nvar app = require('express')();\n\napp.get('/user/:id', function(req, res) {\n\tlet id = req.params.id;\n\tid = id.replace(/<|>/g, \"\"); // BAD\n\tlet userHtml = `
${getUserName(id) || \"Unknown name\"}
`;\n\t// ...\n\tres.send(prefix + userHtml + suffix);\n});\n\n```\nSanitizing the user-controlled data for `\"` helps prevent the vulnerability:\n\n\n```javascript\nvar app = require('express')();\n\napp.get('/user/:id', function(req, res) {\n\tlet id = req.params.id;\n\tid = id.replace(/<|>|&|\"/g, \"\"); // GOOD\n\tlet userHtml = `
${getUserName(id) || \"Unknown name\"}
`;\n\t// ...\n\tres.send(prefix + userHtml + suffix);\n});\n\n```\n\n## References\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* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html).\n"
+ },
+ "properties" : {
+ "tags" : [ "security", "external/cwe/cwe-079", "external/cwe/cwe-116", "external/cwe/cwe-020" ],
+ "description" : "Writing incompletely sanitized values to HTML\n attribute strings can lead to a cross-site\n scripting vulnerability.",
+ "id" : "js/incomplete-html-attribute-sanitization",
+ "kind" : "path-problem",
+ "name" : "Incomplete HTML attribute sanitization",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "6.1"
+ }
+ }, {
+ "id" : "js/bad-tag-filter",
+ "name" : "js/bad-tag-filter",
+ "shortDescription" : {
+ "text" : "Bad HTML filtering regexp"
+ },
+ "fullDescription" : {
+ "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" : "# 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" : [ "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" : "Bad HTML filtering regexp",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "7.8"
+ }
+ }, {
+ "id" : "js/unsafe-html-expansion",
+ "name" : "js/unsafe-html-expansion",
+ "shortDescription" : {
+ "text" : "Unsafe expansion of self-closing HTML tag"
+ },
+ "fullDescription" : {
+ "text" : "Using regular expressions to expand self-closing HTML tags may lead to cross-site scripting vulnerabilities."
+ },
+ "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>$2>\"); // 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>$2>\"); // 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" : [ "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" : "Unsafe expansion of self-closing HTML tag",
+ "precision" : "very-high",
+ "problem.severity" : "warning",
+ "security-severity" : "6.1"
+ }
+ }, {
+ "id" : "js/incomplete-sanitization",
+ "name" : "js/incomplete-sanitization",
+ "shortDescription" : {
+ "text" : "Incomplete string escaping or encoding"
+ },
+ "fullDescription" : {
+ "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" : "# 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" : [ "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",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "7.8"
+ }
+ }, {
+ "id" : "js/double-escaping",
+ "name" : "js/double-escaping",
+ "shortDescription" : {
+ "text" : "Double escaping or unescaping"
+ },
+ "fullDescription" : {
+ "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" : "# 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 `"`.\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 (`"`) 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 `"`.\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 (`"`) 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" : [ "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" : "Double escaping or unescaping",
+ "precision" : "high",
+ "problem.severity" : "warning",
+ "security-severity" : "7.8"
+ }
+ }, {
+ "id" : "js/incomplete-multi-character-sanitization",
+ "name" : "js/incomplete-multi-character-sanitization",
+ "shortDescription" : {
+ "text" : "Incomplete multi-character sanitization"
+ },
+ "fullDescription" : {
+ "text" : "A sanitizer that removes a sequence of characters may reintroduce the dangerous sequence."
+ },
+ "defaultConfiguration" : {
+ "enabled" : true,
+ "level" : "warning"
+ },
+ "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(/