mirror of
https://github.com/github/codeql.git
synced 2026-05-01 03:35:13 +02:00
Merge pull request #1182 from esben-semmle/js/sourcenode-regexp-literals
Approved by xiemaisi
This commit is contained in:
@@ -18,7 +18,7 @@ import javascript
|
||||
*/
|
||||
predicate matchesString(Expr e, string s) {
|
||||
exists(RegExpLiteral rl |
|
||||
rl = e and
|
||||
rl.flow().(DataFlow::SourceNode).flowsToExpr(e) and
|
||||
not rl.isIgnoreCase() and
|
||||
regExpMatchesString(rl.getRoot(), s)
|
||||
)
|
||||
|
||||
@@ -70,7 +70,7 @@ class Replacement extends DataFlow::Node {
|
||||
Replacement() {
|
||||
exists(DataFlow::MethodCallNode mcn | this = mcn |
|
||||
mcn.getMethodName() = "replace" and
|
||||
mcn.getArgument(0).asExpr() = pattern and
|
||||
pattern.flow().(DataFlow::SourceNode).flowsTo(mcn.getArgument(0))and
|
||||
mcn.getNumArgument() = 2 and
|
||||
pattern.isGlobal()
|
||||
)
|
||||
|
||||
@@ -59,7 +59,7 @@ predicate isSimple(RegExpTerm t) {
|
||||
*/
|
||||
predicate isBackslashEscape(MethodCallExpr mce, RegExpLiteral re) {
|
||||
mce.getMethodName() = "replace" and
|
||||
re = mce.getArgument(0) and
|
||||
re.flow().(DataFlow::SourceNode).flowsToExpr(mce.getArgument(0)) and
|
||||
re.isGlobal() and
|
||||
exists(string new | new = mce.getArgument(1).getStringValue() |
|
||||
// `new` is `\$&`, `\$1` or similar
|
||||
@@ -104,7 +104,7 @@ predicate allBackslashesEscaped(DataFlow::Node nd) {
|
||||
from MethodCallExpr repl, Expr old, string msg
|
||||
where
|
||||
repl.getMethodName() = "replace" and
|
||||
old = repl.getArgument(0) and
|
||||
(old = repl.getArgument(0) or old.flow().(DataFlow::SourceNode).flowsToExpr(repl.getArgument(0))) and
|
||||
(
|
||||
not old.(RegExpLiteral).isGlobal() and
|
||||
msg = "This replaces only the first occurrence of " + old + "." and
|
||||
|
||||
@@ -211,6 +211,7 @@ module SourceNode {
|
||||
* - object expressions
|
||||
* - array expressions
|
||||
* - JSX literals
|
||||
* - regular expression literals
|
||||
*
|
||||
* This class is for internal use only and should not normally be used directly.
|
||||
*/
|
||||
@@ -224,7 +225,8 @@ module SourceNode {
|
||||
astNode instanceof ArrayExpr or
|
||||
astNode instanceof JSXNode or
|
||||
astNode instanceof GlobalVarAccess or
|
||||
astNode instanceof ExternalModuleReference
|
||||
astNode instanceof ExternalModuleReference or
|
||||
astNode instanceof RegExpLiteral
|
||||
)
|
||||
or
|
||||
exists(SsaExplicitDefinition ssa, VarDef def |
|
||||
|
||||
@@ -100,7 +100,7 @@ module ClientSideUrlRedirect {
|
||||
or
|
||||
exists(MethodCallExpr mce |
|
||||
queryAccess.asExpr() = mce and
|
||||
mce.calls(any(RegExpLiteral re), "exec") and
|
||||
mce = any(RegExpLiteral re).flow().(DataFlow::SourceNode).getAMethodCall("exec").asExpr() and
|
||||
nd.asExpr() = mce.getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
| sources.js:3:2:3:1 | this |
|
||||
| sources.js:3:2:5:1 | functio ... x+19;\\n} |
|
||||
| sources.js:3:11:3:11 | x |
|
||||
| sources.js:7:1:7:3 | /x/ |
|
||||
| tst.js:1:1:1:0 | this |
|
||||
| tst.js:1:1:1:24 | import ... m 'fs'; |
|
||||
| tst.js:1:10:1:11 | fs |
|
||||
|
||||
@@ -3,3 +3,5 @@ new (x => x);
|
||||
(function(x) {
|
||||
return x+19;
|
||||
})(23);
|
||||
|
||||
/x/;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| IdentityReplacement.js:1:27:1:30 | /"/g | This replaces '"' with itself. |
|
||||
| IdentityReplacement.js:4:14:4:21 | indirect | This replaces '"' with itself. |
|
||||
| tst.js:1:13:1:16 | "\\\\" | This replaces '\\' with itself. |
|
||||
| tst.js:2:13:2:18 | /(\\\\)/ | This replaces '\\' with itself. |
|
||||
| tst.js:3:13:3:17 | /["]/ | This replaces '"' with itself. |
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
var escaped = raw.replace(/"/g, '\"');
|
||||
(function() {
|
||||
var indirect = /"/g;
|
||||
raw.replace(indirect, '\"');
|
||||
});
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
| tst.js:47:7:47:30 | s.repla ... g, "&") | This replacement may produce '&' characters that are double-unescaped $@. | tst.js:48:7:48:32 | s.repla ... , "\\"") | here |
|
||||
| tst.js:53:10:53:33 | s.repla ... , '\\\\') | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:53:10:54:33 | s.repla ... , '\\'') | here |
|
||||
| tst.js:60:7:60:28 | s.repla ... '%25') | This replacement may double-escape '%' characters from $@. | tst.js:59:7:59:28 | s.repla ... '%26') | here |
|
||||
| tst.js:68:10:70:38 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:68:10:69:39 | s.repla ... apos;") | here |
|
||||
|
||||
@@ -60,3 +60,12 @@ function badPercentEscape(s) {
|
||||
s = s.replace(/%/g, '%25');
|
||||
return s;
|
||||
}
|
||||
|
||||
function badEncode(s) {
|
||||
var indirect1 = /"/g;
|
||||
var indirect2 = /'/g;
|
||||
var indirect3 = /&/g;
|
||||
return s.replace(indirect1, """)
|
||||
.replace(indirect2, "'")
|
||||
.replace(indirect3, "&");
|
||||
}
|
||||
|
||||
@@ -15,3 +15,4 @@
|
||||
| tst.js:61:10:61:18 | s.replace | This replaces only the first occurrence of "'" + "". |
|
||||
| tst.js:65:10:65:18 | s.replace | This replaces only the first occurrence of "'". |
|
||||
| tst.js:69:10:69:18 | s.replace | This replaces only the first occurrence of "'" + "". |
|
||||
| tst.js:169:9:169:17 | s.replace | This replaces only the first occurrence of /'/. |
|
||||
|
||||
@@ -163,3 +163,8 @@ app.get('/some/path', function(req, res) {
|
||||
flowifyComments(untrusted);
|
||||
good11(untrusted);
|
||||
});
|
||||
|
||||
(function (s) {
|
||||
var indirect = /'/;
|
||||
return s.replace(indirect, ""); // NOT OK
|
||||
});
|
||||
|
||||
@@ -38,6 +38,10 @@ nodes
|
||||
| tst.js:2:19:2:72 | /.*redi ... ref)[1] |
|
||||
| tst.js:2:47:2:63 | document.location |
|
||||
| tst.js:2:47:2:68 | documen ... on.href |
|
||||
| tst.js:6:20:6:56 | indirec ... n.href) |
|
||||
| tst.js:6:20:6:59 | indirec ... ref)[1] |
|
||||
| tst.js:6:34:6:50 | document.location |
|
||||
| tst.js:6:34:6:55 | documen ... on.href |
|
||||
edges
|
||||
| tst2.js:2:7:2:33 | href | tst2.js:4:21:4:24 | href |
|
||||
| tst2.js:2:7:2:33 | href | tst2.js:4:21:4:24 | href |
|
||||
@@ -69,6 +73,9 @@ edges
|
||||
| tst.js:2:19:2:69 | /.*redi ... n.href) | tst.js:2:19:2:72 | /.*redi ... ref)[1] |
|
||||
| tst.js:2:47:2:63 | document.location | tst.js:2:47:2:68 | documen ... on.href |
|
||||
| tst.js:2:47:2:68 | documen ... on.href | tst.js:2:19:2:69 | /.*redi ... n.href) |
|
||||
| tst.js:6:20:6:56 | indirec ... n.href) | tst.js:6:20:6:59 | indirec ... ref)[1] |
|
||||
| tst.js:6:34:6:50 | document.location | tst.js:6:34:6:55 | documen ... on.href |
|
||||
| tst.js:6:34:6:55 | documen ... on.href | tst.js:6:20:6:56 | indirec ... n.href) |
|
||||
#select
|
||||
| tst2.js:4:21:4:55 | href.su ... '?')+1) | tst2.js:2:14:2:28 | window.location | tst2.js:4:21:4:55 | href.su ... '?')+1) | Untrusted URL redirection due to $@. | tst2.js:2:14:2:28 | window.location | user-provided value |
|
||||
| tst2.js:4:21:4:55 | href.su ... '?')+1) | tst2.js:2:14:2:28 | window.location | tst2.js:4:21:4:55 | href.su ... '?')+1) | Untrusted URL redirection due to $@. | tst2.js:2:14:2:28 | window.location | user-provided value |
|
||||
@@ -84,3 +91,4 @@ edges
|
||||
| tst10.js:11:17:11:50 | '//foo' ... .search | tst10.js:11:27:11:43 | document.location | tst10.js:11:17:11:50 | '//foo' ... .search | Untrusted URL redirection due to $@. | tst10.js:11:27:11:43 | document.location | user-provided value |
|
||||
| tst10.js:14:17:14:56 | 'https: ... .search | tst10.js:14:33:14:49 | document.location | tst10.js:14:17:14:56 | 'https: ... .search | Untrusted URL redirection due to $@. | tst10.js:14:33:14:49 | document.location | user-provided value |
|
||||
| tst.js:2:19:2:72 | /.*redi ... ref)[1] | tst.js:2:47:2:63 | document.location | tst.js:2:19:2:72 | /.*redi ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:2:47:2:63 | document.location | user-provided value |
|
||||
| tst.js:6:20:6:59 | indirec ... ref)[1] | tst.js:6:34:6:50 | document.location | tst.js:6:20:6:59 | indirec ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:6:34:6:50 | document.location | user-provided value |
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
// NOT OK
|
||||
window.location = /.*redirect=([^&]*).*/.exec(document.location.href)[1];
|
||||
|
||||
(function(){
|
||||
var indirect = /.*redirect=([^&]*).*/;
|
||||
window.location = indirect.exec(document.location.href)[1];
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user