@@ -11,25 +11,26 @@ class RegexSink extends DataFlow::ExprNode {
11
11
(
12
12
m .getDeclaringType ( ) instanceof TypeString and
13
13
(
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?)
16
17
m .hasName ( [ "matches" , "split" , "replaceFirst" , "replaceAll" ] )
17
18
)
18
19
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?)
20
21
m .getDeclaringType ( ) .hasQualifiedName ( "java.util.regex" , "Pattern" ) and
21
22
(
22
23
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
24
25
m .hasName ( [ "compile" , "matches" ] )
25
26
)
26
27
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?)
28
29
m .getDeclaringType ( ) .hasQualifiedName ( "org.apache.commons.lang3" , "RegExUtils" ) and
29
30
(
30
31
ma .getArgument ( 1 ) = this .asExpr ( ) and
31
32
m .getParameterType ( 1 ) instanceof TypeString and
32
- // TODO: confirm if more/less than the below need to be handled
33
+ // ! test below more?
33
34
m .hasName ( [
34
35
"removeAll" , "removeFirst" , "removePattern" , "replaceAll" , "replaceFirst" ,
35
36
"replacePattern"
@@ -40,24 +41,38 @@ class RegexSink extends DataFlow::ExprNode {
40
41
}
41
42
}
42
43
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)
44
47
abstract class Sanitizer extends DataFlow:: ExprNode { }
45
48
46
49
/**
47
50
* A call to a function whose name suggests that it escapes regular
48
51
* expression meta-characters.
49
52
*/
53
+ // ! rename as DefaultRegexInjectionSanitizer?
50
54
class RegExpSanitizationCall extends Sanitizer {
51
55
RegExpSanitizationCall ( ) {
52
56
exists ( string calleeName , string sanitize , string regexp |
53
57
calleeName = this .asExpr ( ) .( Call ) .getCallee ( ) .getName ( ) and
58
+ // ! add test case for sanitize? I think current tests only check escape
54
59
sanitize = "(?:escape|saniti[sz]e)" and // TODO: confirm this is sufficient
55
60
regexp = "regexp?" // TODO: confirm this is sufficient
56
61
|
57
62
calleeName
58
63
.regexpMatch ( "(?i)(" + sanitize + ".*" + regexp + ".*)" + "|(" + regexp + ".*" + sanitize +
59
64
".*)" ) // TODO: confirm this is sufficient
60
65
)
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
+ )
61
76
}
62
77
}
63
78
0 commit comments