diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll index c308e6c32c7..eae5f78bb7f 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll @@ -47,7 +47,7 @@ private class StringSummaries extends SummaryModelCsv { ";StringProtocol;true;capitalized(with:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[0].CollectionElement;taint", ";StringProtocol;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[2].CollectionElement.CollectionElement;taint", - ";StringProtocol;true;components(separatedBy:);;;Argument[-1];ReturnValue;taint", + ";StringProtocol;true;components(separatedBy:);;;Argument[-1];ReturnValue.CollectionElement;taint", ";StringProtocol;true;data(using:allowLossyConversion:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;folding(options:locale:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;getBytes(_:maxLength:usedLength:encoding:options:range:remaining:);;;Argument[-1];Argument[0].CollectionElement;taint", diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Url.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Url.qll index 8b4ded353da..ff9aa37769a 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Url.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Url.qll @@ -22,8 +22,7 @@ private class UrlFieldsInheritTaint extends TaintInheritingContent, DataFlow::Co } /** - * A content implying that, if a `URLRequest` is tainted, then its fields `url`, `httpBody`, - * `httpBodyStream`, `mainDocument` and `allHTTPHeaderFields` are tainted. + * A content implying that, if a `URLRequest` is tainted, then certain fields tainted. */ private class UrlRequestFieldsInheritTaint extends TaintInheritingContent, DataFlow::Content::FieldContent @@ -31,7 +30,10 @@ private class UrlRequestFieldsInheritTaint extends TaintInheritingContent, UrlRequestFieldsInheritTaint() { this.getField().getEnclosingDecl().asNominalTypeDecl().getName() = "URLRequest" and this.getField().getName() = - ["url", "httpBody", "httpBodyStream", "mainDocument", "allHTTPHeaderFields"] + [ + "url", "httpBody", "httpBodyStream", "mainDocument", "mainDocumentURL", + "allHTTPHeaderFields" + ] } } diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll index da54683029f..03345227047 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll @@ -39,7 +39,7 @@ private class WKScriptMessageBodyInheritsTaint extends TaintInheritingContent, } /** - * A type or extension delcaration that adopts the protocol `WKNavigationDelegate`. + * A type or extension declaration that adopts the protocol `WKNavigationDelegate`. */ private class AdoptsWkNavigationDelegate extends Decl { AdoptsWkNavigationDelegate() { @@ -74,19 +74,15 @@ private class WKNavigationDelegateSource extends RemoteFlowSource { } /** - * A taint step implying that, if a `WKNavigationAction` is tainted, its `request` field is also tainted. + * A content implying that, if a `WKNavigationAction` is tainted, its + * `request` field is also tainted. */ -private class WKNavigationActionTaintStep extends AdditionalTaintStep { - override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(MemberRefExpr e, Expr self, VarDecl member | - self.getType().getName() = "WKNavigationAction" and - member.getName() = "request" - | - e.getBase() = self and - e.getMember() = member and - n1.asExpr() = self and - n2.asExpr() = e - ) +private class UrlRequestFieldsInheritTaint extends TaintInheritingContent, + DataFlow::Content::FieldContent +{ + UrlRequestFieldsInheritTaint() { + this.getField().getEnclosingDecl().asNominalTypeDecl().getName() = "WKNavigationAction" and + this.getField().getName() = "request" } } diff --git a/swift/ql/test/library-tests/dataflow/taint/libraries/url.swift b/swift/ql/test/library-tests/dataflow/taint/libraries/url.swift index 799eaa85807..b757805380b 100644 --- a/swift/ql/test/library-tests/dataflow/taint/libraries/url.swift +++ b/swift/ql/test/library-tests/dataflow/taint/libraries/url.swift @@ -159,11 +159,12 @@ struct URLRequest : CustomStringConvertible, CustomDebugStringConvertible { enum NetworkServiceType { case none } enum Attribution { case none } var cachePolicy: CachePolicy = .none - var httpMethod: String = "" - var url: URL = URL(string: "")! - var httpBody: Data = Data("") + var httpMethod: String? = "" + var url: URL? = URL(string: "") + var httpBody: Data? = Data("") var httpBodyStream: InputStream? = nil var mainDocument: URL = URL(string: "")! + var mainDocumentURL: URL? = URL(string: "") var allHTTPHeaderFields: [String : String]? = nil var timeoutInterval: TimeInterval = TimeInterval() var httpShouldHandleCookies: Bool = false @@ -204,7 +205,6 @@ func sink(data: Data) {} func sink(string: String) {} func sink(int: Int) {} func sink(any: Any) {} - func taintThroughURL() { let clean = "http://example.com/" let tainted = source() as! String @@ -436,14 +436,16 @@ func taintThroughUrlRequest() { sink(any: tainted.cachePolicy) sink(any: clean.httpMethod) sink(any: tainted.httpMethod) - sink(any: clean.url) - sink(any: tainted.url) // $ tainted=431 - sink(any: clean.httpBody) - sink(any: tainted.httpBody) // $ tainted=431 + sink(any: clean.url!) + sink(any: tainted.url!) // $ tainted=431 + sink(any: clean.httpBody!) + sink(any: tainted.httpBody!) // $ tainted=431 sink(any: clean.httpBodyStream!) sink(any: tainted.httpBodyStream!) // $ tainted=431 sink(any: clean.mainDocument) sink(any: tainted.mainDocument) // $ tainted=431 + sink(any: clean.mainDocumentURL!) + sink(any: tainted.mainDocumentURL!) // $ tainted=431 sink(any: clean.allHTTPHeaderFields!) sink(any: tainted.allHTTPHeaderFields!) // $ tainted=431 sink(any: clean.timeoutInterval) @@ -481,19 +483,19 @@ func taintThroughUrlResource() { let tainted = source() as! URLResource sink(string: clean.name) - sink(string: tainted.name) // $ tainted=481 + sink(string: tainted.name) // $ tainted=483 sink(string: clean.subdirectory!) - sink(string: tainted.subdirectory!) // $ tainted=481 + sink(string: tainted.subdirectory!) // $ tainted=483 } func taintUrlAsync() async throws { let tainted = source() as! String let urlTainted = URL(string: tainted)! - sink(any: urlTainted.lines) // $ tainted=490 + sink(any: urlTainted.lines) // $ tainted=492 for try await line in urlTainted.lines { - sink(string: line) // $ MISSING: tainted=490 + sink(string: line) // $ MISSING: tainted=492 } } @@ -510,5 +512,5 @@ func closureReturnValue() { ptr in return source() as! String }) - sink(string: r2) // $ tainted=511 + sink(string: r2) // $ tainted=513 } diff --git a/swift/ql/test/library-tests/dataflow/taint/libraries/webview.swift b/swift/ql/test/library-tests/dataflow/taint/libraries/webview.swift index 43b291163d6..92fb7d12498 100644 --- a/swift/ql/test/library-tests/dataflow/taint/libraries/webview.swift +++ b/swift/ql/test/library-tests/dataflow/taint/libraries/webview.swift @@ -76,7 +76,7 @@ struct URLRequest {} // --- tests --- -func source() -> Any { return "" } +func source(_ label: String? = "") -> Any { return "" } func sink(_: Any) {} func testInheritBodyTaint() { @@ -146,6 +146,9 @@ func testWKUserScript() { } func testWKNavigationAction() { - let src = source() as! WKNavigationAction - sink(src.request) // $ tainted=149 -} \ No newline at end of file + let src = source("WKNavigationAction") as! WKNavigationAction + sink(src.request) // $ tainted=WKNavigationAction + + let keypath = \WKNavigationAction.request + sink(src[keyPath: keypath]) // $ tainted=WKNavigationAction +}