@@ -8,17 +8,27 @@ import codeql.swift.dataflow.DataFlow
88import codeql.swift.dataflow.FlowSources
99
1010/**
11- * A source of untrusted, user-controlled data .
11+ * A dataflow sink for javascript evaluation vulnerabilities .
1212 */
13- class Source = FlowSource ;
13+ abstract class UnsafeJsEvalSink extends DataFlow :: Node { }
1414
1515/**
16- * A sink that evaluates a string of JavaScript code .
16+ * A sanitizer for javascript evaluation vulnerabilities .
1717 */
18- abstract class Sink extends DataFlow:: Node { }
18+ abstract class UnsafeJsEvalSanitizer extends DataFlow:: Node { }
1919
20- class WKWebView extends Sink {
21- WKWebView ( ) {
20+ /**
21+ * A unit class for adding additional taint steps.
22+ */
23+ class UnsafeJsEvalAdditionalTaintStep extends Unit {
24+ abstract predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) ;
25+ }
26+
27+ /**
28+ * A default SQL injection sink for the `WKWebView` interface.
29+ */
30+ class WKWebViewDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink {
31+ WKWebViewDefaultUnsafeJsEvalSink ( ) {
2232 any ( CallExpr ce |
2333 ce .getStaticTarget ( )
2434 .( MethodDecl )
@@ -34,8 +44,11 @@ class WKWebView extends Sink {
3444 }
3545}
3646
37- class WKUserContentController extends Sink {
38- WKUserContentController ( ) {
47+ /**
48+ * A default SQL injection sink for the `WKUserContentController` interface.
49+ */
50+ class WKUserContentControllerDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink {
51+ WKUserContentControllerDefaultUnsafeJsEvalSink ( ) {
3952 any ( CallExpr ce |
4053 ce .getStaticTarget ( )
4154 .( MethodDecl )
@@ -44,8 +57,11 @@ class WKUserContentController extends Sink {
4457 }
4558}
4659
47- class UIWebView extends Sink {
48- UIWebView ( ) {
60+ /**
61+ * A default SQL injection sink for the `UIWebView` and `WebView` interfaces.
62+ */
63+ class UIWebViewDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink {
64+ UIWebViewDefaultUnsafeJsEvalSink ( ) {
4965 any ( CallExpr ce |
5066 ce .getStaticTarget ( )
5167 .( MethodDecl )
@@ -54,8 +70,11 @@ class UIWebView extends Sink {
5470 }
5571}
5672
57- class JSContext extends Sink {
58- JSContext ( ) {
73+ /**
74+ * A default SQL injection sink for the `JSContext` interface.
75+ */
76+ class JSContextDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink {
77+ JSContextDefaultUnsafeJsEvalSink ( ) {
5978 any ( CallExpr ce |
6079 ce .getStaticTarget ( )
6180 .( MethodDecl )
@@ -64,10 +83,61 @@ class JSContext extends Sink {
6483 }
6584}
6685
67- class JSEvaluateScript extends Sink {
68- JSEvaluateScript ( ) {
86+ /**
87+ * A default SQL injection sink for the `JSEvaluateScript` function.
88+ */
89+ class JSEvaluateScriptDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink {
90+ JSEvaluateScriptDefaultUnsafeJsEvalSink ( ) {
6991 any ( CallExpr ce |
7092 ce .getStaticTarget ( ) .( FreeFunctionDecl ) .hasName ( "JSEvaluateScript(_:_:_:_:_:_:)" )
7193 ) .getArgument ( 1 ) .getExpr ( ) = this .asExpr ( )
7294 }
7395}
96+
97+ /**
98+ * A default SQL injection sanitrizer.
99+ */
100+ class DefaultUnsafeJsEvalAdditionalTaintStep extends UnsafeJsEvalAdditionalTaintStep {
101+ override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
102+ exists ( Argument arg |
103+ arg =
104+ any ( CallExpr ce |
105+ ce .getStaticTarget ( ) .( MethodDecl ) .hasQualifiedName ( "String" , "init(decoding:as:)" )
106+ ) .getArgument ( 0 )
107+ or
108+ arg =
109+ any ( CallExpr ce |
110+ ce .getStaticTarget ( )
111+ .( FreeFunctionDecl )
112+ .hasName ( [
113+ "JSStringCreateWithUTF8CString(_:)" , "JSStringCreateWithCharacters(_:_:)" ,
114+ "JSStringRetain(_:)"
115+ ] )
116+ ) .getArgument ( 0 )
117+ |
118+ nodeFrom .asExpr ( ) = arg .getExpr ( ) and
119+ nodeTo .asExpr ( ) = arg .getApplyExpr ( )
120+ )
121+ or
122+ exists ( CallExpr ce , Expr self , AbstractClosureExpr closure |
123+ ce .getStaticTarget ( )
124+ .getName ( )
125+ .matches ( [ "withContiguousStorageIfAvailable(%)" , "withUnsafeBufferPointer(%)" ] ) and
126+ self = ce .getQualifier ( ) and
127+ ce .getArgument ( 0 ) .getExpr ( ) = closure
128+ |
129+ nodeFrom .asExpr ( ) = self and
130+ nodeTo .( DataFlow:: ParameterNode ) .getParameter ( ) = closure .getParam ( 0 )
131+ )
132+ or
133+ exists ( MemberRefExpr e , Expr self , VarDecl member |
134+ self .getType ( ) .getName ( ) .matches ( [ "Unsafe%Buffer%" , "Unsafe%Pointer%" ] ) and
135+ member .getName ( ) = "baseAddress"
136+ |
137+ e .getBase ( ) = self and
138+ e .getMember ( ) = member and
139+ nodeFrom .asExpr ( ) = self and
140+ nodeTo .asExpr ( ) = e
141+ )
142+ }
143+ }
0 commit comments