mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
JS: Use return value of trusted type policy callback as a sink
This commit is contained in:
@@ -126,6 +126,7 @@ import semmle.javascript.frameworks.SocketIO
|
||||
import semmle.javascript.frameworks.StringFormatters
|
||||
import semmle.javascript.frameworks.TorrentLibraries
|
||||
import semmle.javascript.frameworks.Typeahead
|
||||
import semmle.javascript.frameworks.TrustedTypes
|
||||
import semmle.javascript.frameworks.UriLibraries
|
||||
import semmle.javascript.frameworks.Vue
|
||||
import semmle.javascript.frameworks.Vuex
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/** Module for working with uses of the Trusted Types API. */
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.security.dataflow.Xss
|
||||
private import semmle.javascript.security.dataflow.ClientSideUrlRedirectCustomizations
|
||||
private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
|
||||
|
||||
/** Module for working with uses of the Trusted Types API. */
|
||||
module TrustedTypes {
|
||||
private class TrustedTypesEntry extends API::EntryPoint {
|
||||
TrustedTypesEntry() { this = "TrustedTypesEntry" }
|
||||
|
||||
override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("trustedTypes") }
|
||||
|
||||
override DataFlow::Node getARhs() { none() }
|
||||
}
|
||||
|
||||
private API::Node trustedTypesObj() { result = any(TrustedTypesEntry entry).getNode() }
|
||||
|
||||
/** A call to `trustedTypes.createPolicy`. */
|
||||
class PolicyCreation extends API::CallNode {
|
||||
PolicyCreation() { this = trustedTypesObj().getMember("createPolicy").getACall() }
|
||||
|
||||
DataFlow::FunctionNode getPolicyCallback(string method) {
|
||||
// Require local callback to avoid potential call/return mismatch in the uses below
|
||||
result = getOptionArgument(1, method).getALocalSource()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow step from the use of a policy to its callback.
|
||||
*/
|
||||
private class PolicyInputStep extends DataFlow::SharedFlowStep {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(PolicyCreation policy, string method |
|
||||
pred = policy.getReturn().getMember(method).getParameter(0).getARhs() and
|
||||
succ = policy.getPolicyCallback(method).getParameter(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The creation of a trusted HTML object, as an XSS sink.
|
||||
*/
|
||||
private class XssSink extends DomBasedXss::Sink {
|
||||
XssSink() { this = any(PolicyCreation creation).getPolicyCallback("createHTML").getAReturn() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The creation of a trusted script, as a code-injection sink.
|
||||
*/
|
||||
private class CodeInjectionSink extends CodeInjection::Sink {
|
||||
CodeInjectionSink() {
|
||||
this = any(PolicyCreation creation).getPolicyCallback("createScript").getAReturn()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The creation of a trusted script URL, as a URL redirection sink.
|
||||
*
|
||||
* This is currently handled by the client-side URL redirection query, as this checks for untrusted hostname in the URL.
|
||||
*/
|
||||
private class UrlSink extends ClientSideUrlRedirect::Sink {
|
||||
UrlSink() {
|
||||
this = any(PolicyCreation creation).getPolicyCallback("createScriptURL").getAReturn()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -427,6 +427,11 @@ nodes
|
||||
| translate.js:7:42:7:60 | target.substring(1) |
|
||||
| translate.js:9:27:9:50 | searchP ... 'term') |
|
||||
| translate.js:9:27:9:50 | searchP ... 'term') |
|
||||
| trusted-types.js:2:66:2:66 | x |
|
||||
| trusted-types.js:2:71:2:71 | x |
|
||||
| trusted-types.js:2:71:2:71 | x |
|
||||
| trusted-types.js:3:24:3:34 | window.name |
|
||||
| trusted-types.js:3:24:3:34 | window.name |
|
||||
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) |
|
||||
| tst3.js:2:23:2:74 | decodeU ... str(1)) |
|
||||
| tst3.js:2:42:2:63 | window. ... .search |
|
||||
@@ -1183,6 +1188,10 @@ edges
|
||||
| translate.js:7:42:7:47 | target | translate.js:7:42:7:60 | target.substring(1) |
|
||||
| translate.js:7:42:7:60 | target.substring(1) | translate.js:9:27:9:50 | searchP ... 'term') |
|
||||
| translate.js:7:42:7:60 | target.substring(1) | translate.js:9:27:9:50 | searchP ... 'term') |
|
||||
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
|
||||
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
|
||||
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
|
||||
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
|
||||
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:4:25:4:28 | data |
|
||||
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:5:26:5:29 | data |
|
||||
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:7:32:7:35 | data |
|
||||
@@ -1612,6 +1621,7 @@ edges
|
||||
| tooltip.jsx:10:25:10:30 | source | tooltip.jsx:6:20:6:30 | window.name | tooltip.jsx:10:25:10:30 | source | Cross-site scripting vulnerability due to $@. | tooltip.jsx:6:20:6:30 | window.name | user-provided value |
|
||||
| tooltip.jsx:11:25:11:30 | source | tooltip.jsx:6:20:6:30 | window.name | tooltip.jsx:11:25:11:30 | source | Cross-site scripting vulnerability due to $@. | tooltip.jsx:6:20:6:30 | window.name | user-provided value |
|
||||
| translate.js:9:27:9:50 | searchP ... 'term') | translate.js:6:16:6:39 | documen ... .search | translate.js:9:27:9:50 | searchP ... 'term') | Cross-site scripting vulnerability due to $@. | translate.js:6:16:6:39 | documen ... .search | user-provided value |
|
||||
| trusted-types.js:2:71:2:71 | x | trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:71:2:71 | x | Cross-site scripting vulnerability due to $@. | trusted-types.js:3:24:3:34 | window.name | user-provided value |
|
||||
| tst3.js:4:25:4:32 | data.src | tst3.js:2:42:2:63 | window. ... .search | tst3.js:4:25:4:32 | data.src | Cross-site scripting vulnerability due to $@. | tst3.js:2:42:2:63 | window. ... .search | user-provided value |
|
||||
| tst3.js:5:26:5:31 | data.p | tst3.js:2:42:2:63 | window. ... .search | tst3.js:5:26:5:31 | data.p | Cross-site scripting vulnerability due to $@. | tst3.js:2:42:2:63 | window. ... .search | user-provided value |
|
||||
| tst3.js:7:32:7:37 | data.p | tst3.js:2:42:2:63 | window. ... .search | tst3.js:7:32:7:37 | data.p | Cross-site scripting vulnerability due to $@. | tst3.js:2:42:2:63 | window. ... .search | user-provided value |
|
||||
|
||||
@@ -434,6 +434,11 @@ nodes
|
||||
| translate.js:7:42:7:60 | target.substring(1) |
|
||||
| translate.js:9:27:9:50 | searchP ... 'term') |
|
||||
| translate.js:9:27:9:50 | searchP ... 'term') |
|
||||
| trusted-types.js:2:66:2:66 | x |
|
||||
| trusted-types.js:2:71:2:71 | x |
|
||||
| trusted-types.js:2:71:2:71 | x |
|
||||
| trusted-types.js:3:24:3:34 | window.name |
|
||||
| trusted-types.js:3:24:3:34 | window.name |
|
||||
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) |
|
||||
| tst3.js:2:23:2:74 | decodeU ... str(1)) |
|
||||
| tst3.js:2:42:2:63 | window. ... .search |
|
||||
@@ -1218,6 +1223,10 @@ edges
|
||||
| translate.js:7:42:7:47 | target | translate.js:7:42:7:60 | target.substring(1) |
|
||||
| translate.js:7:42:7:60 | target.substring(1) | translate.js:9:27:9:50 | searchP ... 'term') |
|
||||
| translate.js:7:42:7:60 | target.substring(1) | translate.js:9:27:9:50 | searchP ... 'term') |
|
||||
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
|
||||
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
|
||||
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
|
||||
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
|
||||
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:4:25:4:28 | data |
|
||||
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:5:26:5:29 | data |
|
||||
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:7:32:7:35 | data |
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
(function() {
|
||||
const policy1 = trustedTypes.createPolicy('x', { createHTML: x => x }); // NOT OK
|
||||
policy1.createHTML(window.name);
|
||||
|
||||
const policy2 = trustedTypes.createPolicy('x', { createHTML: x => 'safe' }); // OK
|
||||
policy2.createHTML(window.name);
|
||||
|
||||
const policy3 = trustedTypes.createPolicy('x', { createHTML: x => x }); // OK
|
||||
policy3.createHTML('safe');
|
||||
})();
|
||||
Reference in New Issue
Block a user