Deprecated UIWebView Usage
ID |
swift.deprecated_uiwebview |
Severity |
info |
Resource |
Misconfiguration |
Language |
Swift |
Tags |
CWE:477, NIST.SP.800-53, OWASP:2021:A06 |
Description
UIWebView is a deprecated iOS component that was officially deprecated by Apple in iOS 12.0 and removed from SDK documentation. Apple strongly recommends migrating to WKWebView from the WebKit framework, which provides significantly improved security, performance, and modern web standards support.
Using deprecated UIWebView in applications creates several risks:
-
No security updates: UIWebView no longer receives security patches, leaving applications vulnerable to known web-based exploits
-
App Store rejection: Apple may reject or remove applications that use UIWebView
-
Lack of process isolation: UIWebView runs web content in the same process as the application, meaning web content exploits can directly compromise the app
-
Poor JavaScript performance: Uses older JavaScript engine with limited optimization
-
Missing modern web features: Lacks support for modern web APIs and standards
-
No sandboxing: Web content has excessive access to application resources
WKWebView, introduced in iOS 8.0, addresses these issues by:
-
Running web content in a separate process with strong sandboxing
-
Using the modern Nitro JavaScript engine for better performance
-
Providing granular security controls and content filtering
-
Receiving ongoing security updates and improvements
-
Supporting modern web standards and APIs
-
Offering better memory management
Rationale
This detector reports the first occurrence of UIWebView usage in each source file. The detector identifies:
-
Variable declarations with UIWebView type:
var webView: UIWebView -
Property declarations with UIWebView type:
@IBOutlet var webView: UIWebView! -
UIWebView instance creation:
UIWebView(frame: …) -
Class inheritance from UIWebView:
class CustomView: UIWebView -
Type references to UIWebView:
let view: UIWebView?
The detector avoids reporting multiple issues in the same file to prevent noise and allows developers to migrate entire files at once.
The following example demonstrates vulnerable code:
import UIKit
// VULNERABLE: Using deprecated UIWebView
class LegacyWebViewController: UIViewController {
// FLAW: UIWebView property declaration
var webView: UIWebView?
override func viewDidLoad() {
super.viewDidLoad()
// FLAW: Creating UIWebView instance
webView = UIWebView(frame: view.bounds)
webView?.delegate = self
view.addSubview(webView!)
}
func loadWebpage(_ urlString: String) {
if let url = URL(string: urlString) {
let request = URLRequest(url: url)
// FLAW: Loading content in deprecated UIWebView
webView?.loadRequest(request)
}
}
func loadHTMLContent(_ html: String) {
// FLAW: Loading HTML in UIWebView without sandboxing
webView?.loadHTMLString(html, baseURL: nil)
}
func executeJavaScript(_ script: String) {
// FLAW: JavaScript execution in same process as app
let result = webView?.stringByEvaluatingJavaScript(from: script)
print("Script result: \(result ?? "")")
}
}
Using UIWebView has several problems:
-
Deprecated API:
UIWebViewis deprecated and no longer receives security updates from Apple. -
Security vulnerabilities: Any security flaws discovered in UIWebView will not be patched, leaving the application vulnerable to XSS, CSRF, and other web-based attacks.
-
No process isolation: Web content runs in the same process as the application, meaning exploits in web content can directly compromise the app’s memory and data.
-
App Store compliance: Apple actively discourages UIWebView usage and may reject applications during App Store review.
-
Limited security controls: UIWebView provides minimal security configuration options compared to WKWebView.
Remediation
The recommended approach is to migrate to WKWebView. Replace all UIWebView usage with WKWebView from the WebKit framework.
You can use WKWebViewConfiguration to configure the web view to avoid security issues, particularly when using external, untrusted content:
import UIKit
import WebKit
// SECURE: Using modern WKWebView
class ModernWebViewController: UIViewController, WKNavigationDelegate {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
// SECURE: Create WKWebView with configuration
let configuration = WKWebViewConfiguration()
// Enable additional security features
configuration.preferences.javaScriptCanOpenWindowsAutomatically = false
// iOS 14+: Control media playback
if #available(iOS 14.0, *) {
configuration.defaultWebpagePreferences.allowsContentJavaScript = true
}
// Create WKWebView with secure configuration
webView = WKWebView(frame: view.bounds, configuration: configuration)
webView.navigationDelegate = self
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(webView)
}
// SECURE: Load webpage with WKWebView
func loadWebpage(_ urlString: String) {
if let url = URL(string: urlString) {
let request = URLRequest(url: url)
webView.load(request)
}
}
// SECURE: Load HTML content with WKWebView
func loadHTMLContent(_ html: String) {
webView.loadHTMLString(html, baseURL: nil)
}
// SECURE: Execute JavaScript with modern API
func executeJavaScript(_ script: String) {
webView.evaluateJavaScript(script) { result, error in
if let error = error {
print("JavaScript error: \(error)")
return
}
print("Script result: \(result ?? "")")
}
}
// SECURE: WKNavigationDelegate provides better security controls
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// Implement security policies
guard let url = navigationAction.request.url else {
decisionHandler(.cancel)
return
}
// Only allow HTTPS connections
if url.scheme != "https" && url.scheme != "file" {
print("Blocked non-HTTPS URL: \(url)")
decisionHandler(.cancel)
return
}
// Implement domain whitelist
let allowedDomains = ["example.com", "trusted-domain.com"]
if let host = url.host, allowedDomains.contains(where: { url.host?.hasSuffix($0) ?? false }) {
decisionHandler(.allow)
} else {
print("Blocked untrusted domain: \(url.host ?? "unknown")")
decisionHandler(.cancel)
}
}
// SECURE: Handle navigation errors
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print("Navigation failed: \(error.localizedDescription)")
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!,
withError error: Error) {
print("Provisional navigation failed: \(error.localizedDescription)")
}
}
References
-
CWE-477: Use of Obsolete Function.
-
OWASP - Top 10 2021 Category A06 : Vulnerable and Outdated Components.