diff --git a/javascript/ql/src/semmle/javascript/Regexp.qll b/javascript/ql/src/semmle/javascript/Regexp.qll index 842cf0705c72..1a27f001d600 100644 --- a/javascript/ql/src/semmle/javascript/Regexp.qll +++ b/javascript/ql/src/semmle/javascript/Regexp.qll @@ -191,6 +191,19 @@ class RegExpQuantifier extends RegExpTerm, @regexp_quantifier { predicate isGreedy() { is_greedy(this) } } +/** + * A regular expression term that permits unlimited repetitions. + */ +class InfiniteRepetitionQuantifier extends RegExpQuantifier { + InfiniteRepetitionQuantifier() { + this instanceof RegExpPlus + or + this instanceof RegExpStar + or + this instanceof RegExpRange and not exists(this.(RegExpRange).getUpperBound()) + } +} + /** * An escaped regular expression term, that is, a regular expression * term starting with a backslash. @@ -1065,6 +1078,12 @@ module RegExp { not cls.isInverted() and cls.getAChild().(RegExpCharacterClassEscape).getValue().isUppercase() ) + or + // an unlimited number of wildcards, is also a wildcard. + exists(InfiniteRepetitionQuantifier q | + term = q and + isWildcardLike(q.getAChild()) + ) } /** diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll index 6a7bd111a9fe..81e69a5229b6 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll @@ -34,7 +34,12 @@ module Shared { class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall { MetacharEscapeSanitizer() { isGlobal() and - RegExp::alwaysMatchesMetaCharacter(getRegExp().getRoot(), ["<", "'", "\""]) + ( + RegExp::alwaysMatchesMetaCharacter(getRegExp().getRoot(), ["<", "'", "\""]) + or + // or it's like a wild-card. + RegExp::isWildcardLike(getRegExp().getRoot()) + ) } } diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index ae2917920d7b..a6f91c595dd0 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -53,19 +53,6 @@ private predicate isReDoSCandidate(State state, string pump) { ) } -/** - * A regular expression term that permits unlimited repetitions. - */ -class InfiniteRepetitionQuantifier extends RegExpQuantifier { - InfiniteRepetitionQuantifier() { - this instanceof RegExpPlus - or - this instanceof RegExpStar - or - this instanceof RegExpRange and not exists(this.(RegExpRange).getUpperBound()) - } -} - /** * Gets the char after `c` (from a simplified ASCII table). */ diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js index 0e6555fe5685..656f233ca9e3 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js @@ -85,4 +85,8 @@ $("#id").html(anser.ansiToHtml(text)); // NOT OK $("#id").html(new anser().process(text)); // NOT OK + + $("section h1").each(function(){ + $("nav ul").append("Section"); // OK + }); })(); \ No newline at end of file