flawopen.com/XSS in Swift/loadHTMLString
Is iOS WKWebView.loadHTMLString safe for untrusted content?
No, not automatically: WKWebView parses the supplied string as HTML, so tags and script-capable markup remain active unless the content is trusted or handled for the right context. Plain text and user-authored rich HTML need different controls.
Doing it safely
let html = "\(untrustedText)
" webView.loadHTMLString(html, baseURL: nil)
func escapeHTMLText(_ value: String) -> String {
value
.replacingOccurrences(of: "&", with: "&")
.replacingOccurrences(of: "<", with: "<")
.replacingOccurrences(of: ">", with: ">")
.replacingOccurrences(of: "\"", with: """)
.replacingOccurrences(of: "'", with: "'")
}
let html = "\(escapeHTMLText(untrustedText))
"
webView.loadHTMLString(html, baseURL: nil)
The extra risk to check for
A page-world message handler gives scripts in the page a route into app code. `WKContentWorld` can separate JavaScript environments, but the page and app scripts still share the DOM. If untrusted HTML and a bridge coexist, expose only the minimum capability, validate the message and its frame, and authorize each operation; do not treat world separation as authorization.
What baseURL controls
Apple documents `baseURL` as the base used to resolve relative URLs in the supplied HTML. It does not sanitize markup or disable page JavaScript. Setting it to `nil` is not an XSS or sandbox control; decide resource and navigation policy separately.
Choose a control for each boundary
For plain text inside an HTML text node, use a text-node-specific encoder such as the one below; do not reuse it in attributes, URLs, CSS, or JavaScript. For user-authored rich HTML, use a maintained sanitizer with explicit element, attribute, and URL-scheme allowlists. Pass values to app-supplied JavaScript with `callAsyncJavaScript` arguments instead of interpolating them into source. If the page needs no JavaScript, `allowsContentJavaScript` can disable page scripts as defense in depth; it does not replace correct output handling.
FAQ
No — it carries the identical risk, and has no additional sanitization built in either. Migrating to WKWebView is a modernization step, not a safety fix on its own.
No. Apple documents `baseURL` for resolving relative URLs. It is not an HTML sanitizer, script switch, or sandbox guarantee.
No. It separates JavaScript environments while they share the DOM. Treat DOM data and messages as untrusted, and authorize every native operation independently.
References
- Apple Developer — WKWebView
- flawopen.com — XSS in Swift
- Apple — WKWebView.callAsyncJavaScript(_:arguments:in:in:completionHandler:)
- Apple — WKContentWorld
- Apple — WKUserContentController.add(_:contentWorld:name:)
- Apple — WKWebpagePreferences.allowsContentJavaScript
- OWASP — Cross Site Scripting Prevention Cheat Sheet
- Apple — WKWebView.loadHTMLString(_:baseURL:)