mirror of
https://github.com/github/codeql.git
synced 2025-12-21 19:26:31 +01:00
JS: Share more code with Ruby
This commit is contained in:
@@ -157,3 +157,46 @@ private predicate isCommonWordMatcher(RegExpTerm t) {
|
|||||||
.getValue() = "w"
|
.getValue() = "w"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `replace` has a pattern argument containing a regular expression
|
||||||
|
* `dangerous` which matches a dangerous string beginning with `prefix`, in an
|
||||||
|
* attempt to avoid a vulnerability of kind `kind`.
|
||||||
|
*/
|
||||||
|
predicate isResult(
|
||||||
|
StringSubstitutionCall replace, EmptyReplaceRegExpTerm dangerous, string prefix, string kind
|
||||||
|
) {
|
||||||
|
exists(EmptyReplaceRegExpTerm regexp |
|
||||||
|
replace = regexp.getCall() and
|
||||||
|
dangerous.getRootTerm() = regexp and
|
||||||
|
// skip leading optional elements
|
||||||
|
not dangerous.isNullable() and
|
||||||
|
// only warn about the longest match
|
||||||
|
prefix = max(string m | matchesDangerousPrefix(dangerous, m, kind) | m order by m.length(), m) and
|
||||||
|
// only warn once per kind
|
||||||
|
not exists(EmptyReplaceRegExpTerm other |
|
||||||
|
other = dangerous.getAChild+() or other = dangerous.getPredecessor+()
|
||||||
|
|
|
||||||
|
matchesDangerousPrefix(other, _, kind) and
|
||||||
|
not other.isNullable()
|
||||||
|
) and
|
||||||
|
// avoid anchored terms
|
||||||
|
not exists(RegExpAnchor a | regexp = a.getRootTerm()) and
|
||||||
|
// Don't flag replace operations that are called repeatedly in a loop, as they can actually work correctly.
|
||||||
|
not replace.flowsTo(replace.getReceiver+())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `replace` has a pattern argument containing a regular expression
|
||||||
|
* `dangerous` which matches a dangerous string beginning with `prefix`. `msg`
|
||||||
|
* is the alert we report.
|
||||||
|
*/
|
||||||
|
query predicate problems(
|
||||||
|
StringSubstitutionCall replace, string msg, EmptyReplaceRegExpTerm dangerous, string prefix
|
||||||
|
) {
|
||||||
|
exists(string kind |
|
||||||
|
isResult(replace, dangerous, prefix, kind) and
|
||||||
|
msg = "This string may still contain $@, which may cause a " + kind + " vulnerability."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
import javascript
|
import javascript
|
||||||
import semmle.javascript.security.performance.ReDoSUtil as ReDoSUtil
|
import semmle.javascript.security.performance.ReDoSUtil as ReDoSUtil
|
||||||
|
|
||||||
|
class StringSubstitutionCall = StringReplaceCall;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A regexp term that matches substrings that should be replaced with the empty string.
|
* A regexp term that matches substrings that should be replaced with the empty string.
|
||||||
*/
|
*/
|
||||||
@@ -15,4 +17,9 @@ class EmptyReplaceRegExpTerm extends RegExpTerm {
|
|||||||
this = replace.getRegExp().getRoot().getAChild*()
|
this = replace.getRegExp().getRoot().getAChild*()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the substitution call that uses this regexp term.
|
||||||
|
*/
|
||||||
|
StringSubstitutionCall getCall() { this = result.getRegExp().getRoot() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,29 +13,4 @@
|
|||||||
* external/cwe/cwe-116
|
* external/cwe/cwe-116
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import javascript
|
import semmle.javascript.security.IncompleteMultiCharacterSanitization
|
||||||
private import semmle.javascript.security.IncompleteMultiCharacterSanitization
|
|
||||||
|
|
||||||
from
|
|
||||||
StringReplaceCall replace, EmptyReplaceRegExpTerm regexp, EmptyReplaceRegExpTerm dangerous,
|
|
||||||
string prefix, string kind
|
|
||||||
where
|
|
||||||
regexp = replace.getRegExp().getRoot() and
|
|
||||||
dangerous.getRootTerm() = regexp and
|
|
||||||
// skip leading optional elements
|
|
||||||
not dangerous.isNullable() and
|
|
||||||
// only warn about the longest match (presumably the most descriptive)
|
|
||||||
prefix = max(string m | matchesDangerousPrefix(dangerous, m, kind) | m order by m.length(), m) and
|
|
||||||
// only warn once per kind
|
|
||||||
not exists(EmptyReplaceRegExpTerm other |
|
|
||||||
other = dangerous.getAChild+() or other = dangerous.getPredecessor+()
|
|
||||||
|
|
|
||||||
matchesDangerousPrefix(other, _, kind) and
|
|
||||||
not other.isNullable()
|
|
||||||
) and
|
|
||||||
// don't flag replace operations in a loop
|
|
||||||
not replace.getAMethodCall*().flowsTo(replace.getReceiver()) and
|
|
||||||
// avoid anchored terms
|
|
||||||
not exists(RegExpAnchor a | regexp = a.getRootTerm())
|
|
||||||
select replace, "This string may still contain $@, which may cause a " + kind + " vulnerability.",
|
|
||||||
dangerous, prefix
|
|
||||||
|
|||||||
Reference in New Issue
Block a user