@@ -11,25 +11,26 @@ class RegexSink extends DataFlow::ExprNode {
1111 (
1212 m .getDeclaringType ( ) instanceof TypeString and
1313 (
14- ma .getArgument ( 0 ) = this .asExpr ( ) and
15- // TODO: confirm if more/less than the below need to be handled
14+ ma .getArgument ( 0 ) = this .asExpr ( ) and // ! combine this line with the below at least? e.g. TypeString and TypePattern both use it
15+ // ! test below more?
16+ // ! (are there already classes for these methods in a regex library?)
1617 m .hasName ( [ "matches" , "split" , "replaceFirst" , "replaceAll" ] )
1718 )
1819 or
19- // TODO: review Java Pattern API
20+ // ! make class for the below? (is there already a class for this and its methods in a regex library?)
2021 m .getDeclaringType ( ) .hasQualifiedName ( "java.util.regex" , "Pattern" ) and
2122 (
2223 ma .getArgument ( 0 ) = this .asExpr ( ) and
23- // TODO: confirm if more/less than the below need to be handled
24+ // ! look into further: Pattern.matcher, .pattern() and .toString() as taint steps, .split and .splitAsStream
2425 m .hasName ( [ "compile" , "matches" ] )
2526 )
2627 or
27- // TODO: read docs about regex APIs in Java
28+ // ! make class for the below? (is there already a class for this and its methods in a regex library?)
2829 m .getDeclaringType ( ) .hasQualifiedName ( "org.apache.commons.lang3" , "RegExUtils" ) and
2930 (
3031 ma .getArgument ( 1 ) = this .asExpr ( ) and
3132 m .getParameterType ( 1 ) instanceof TypeString and
32- // TODO: confirm if more/less than the below need to be handled
33+ // ! test below more?
3334 m .hasName ( [
3435 "removeAll" , "removeFirst" , "removePattern" , "replaceAll" , "replaceFirst" ,
3536 "replacePattern"
@@ -40,24 +41,38 @@ class RegexSink extends DataFlow::ExprNode {
4041 }
4142}
4243
43- // TODO: is this abstract class needed? Are there pre-existing sanitizer classes that can be used instead?
44+ // ! keep and rename to RegexInjectionSanitizer IF makes sense to have two sanitizers extending it?;
45+ // ! else, ask Tony/others about if stylistically better to keep it (see default example in LogInjection.qll, etc.)
46+ // ! maybe make abstract classes for source and sink as well (if you do this, mention it in PR description as an attempt to be similar to the other languages' implementations)
4447abstract class Sanitizer extends DataFlow:: ExprNode { }
4548
4649/**
4750 * A call to a function whose name suggests that it escapes regular
4851 * expression meta-characters.
4952 */
53+ // ! rename as DefaultRegexInjectionSanitizer?
5054class RegExpSanitizationCall extends Sanitizer {
5155 RegExpSanitizationCall ( ) {
5256 exists ( string calleeName , string sanitize , string regexp |
5357 calleeName = this .asExpr ( ) .( Call ) .getCallee ( ) .getName ( ) and
58+ // ! add test case for sanitize? I think current tests only check escape
5459 sanitize = "(?:escape|saniti[sz]e)" and // TODO: confirm this is sufficient
5560 regexp = "regexp?" // TODO: confirm this is sufficient
5661 |
5762 calleeName
5863 .regexpMatch ( "(?i)(" + sanitize + ".*" + regexp + ".*)" + "|(" + regexp + ".*" + sanitize +
5964 ".*)" ) // TODO: confirm this is sufficient
6065 )
66+ or
67+ // adds Pattern.quote() as a sanitizer
68+ // see https://rules.sonarsource.com/java/RSPEC-2631 and https://sensei.securecodewarrior.com/recipes/scw:java:regex-injection
69+ exists ( MethodAccess ma , Method m | m = ma .getMethod ( ) |
70+ m .getDeclaringType ( ) .hasQualifiedName ( "java.util.regex" , "Pattern" ) and
71+ (
72+ ma .getArgument ( 0 ) = this .asExpr ( ) and
73+ m .hasName ( "quote" )
74+ )
75+ )
6176 }
6277}
6378
0 commit comments