Skip to content

Commit 562a38c

Browse files
committed
add ContainsHTMLGuard
1 parent 593d4c0 commit 562a38c

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,26 @@ module Shared {
7373
e = this.getBaseString().getEnclosingExpr() and outcome = this.getPolarity().booleanNot()
7474
}
7575
}
76+
77+
/**
78+
* A sanitizer guard that checks for the existence of HTML chars in a string.
79+
* E.g. `/["'&<>]/.exec(str)`.
80+
*/
81+
class ContainsHTMLGuard extends SanitizerGuard, DataFlow::MethodCallNode {
82+
DataFlow::RegExpCreationNode regExp;
83+
84+
ContainsHTMLGuard() {
85+
this.getMethodName() = ["test", "exec"] and
86+
this.getReceiver().getALocalSource() = regExp and
87+
regExp.getRoot() instanceof RegExpCharacterClass and
88+
forall(string s | s = ["\"", "&", "<", ">"] | regExp.getRoot().getAMatchedString() = s)
89+
}
90+
91+
override predicate sanitizes(boolean outcome, Expr e) {
92+
outcome = false and e = this.getArgument(0).asExpr()
93+
}
94+
}
95+
7696
}
7797

7898
/** Provides classes and predicates for the DOM-based XSS query. */
@@ -359,6 +379,8 @@ module DomBasedXss {
359379
)
360380
)
361381
}
382+
383+
private class ContainsHTMLGuard extends SanitizerGuard, Shared::ContainsHTMLGuard { }
362384
}
363385

364386
/** Provides classes and predicates for the reflected XSS query. */
@@ -463,6 +485,8 @@ module ReflectedXss {
463485
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
464486

465487
private class QuoteGuard extends SanitizerGuard, Shared::QuoteGuard { }
488+
489+
private class ContainsHTMLGuard extends SanitizerGuard, Shared::ContainsHTMLGuard { }
466490
}
467491

468492
/** Provides classes and predicates for the stored XSS query. */
@@ -496,6 +520,8 @@ module StoredXss {
496520
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
497521

498522
private class QuoteGuard extends SanitizerGuard, Shared::QuoteGuard { }
523+
524+
private class ContainsHTMLGuard extends SanitizerGuard, Shared::ContainsHTMLGuard { }
499525
}
500526

501527
/** Provides classes and predicates for the XSS through DOM query. */

javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssGood.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,22 @@ app.get('/echo', function(req, res) {
4949
res.setHeader('Content-Length', msg.length);
5050
res.end(msg);
5151
});
52+
53+
app.get('/user/:id', function(req, res) {
54+
const url = req.params.id;
55+
if (!/["'&<>]/.exec(url)) {
56+
res.send(url); // OK
57+
}
58+
});
59+
60+
function escapeHtml1 (str) {
61+
if (!/["'&<>]/.exec(str)) {
62+
return str;
63+
}
64+
}
65+
66+
app.get('/user/:id', function(req, res) {
67+
const url = req.params.id;
68+
69+
res.send(escapeHtml1(url)); // OK
70+
});

0 commit comments

Comments
 (0)