FlawOpen

flawopen.com/XSS in Swift/loadHTMLString

Is iOS WKWebView.loadHTMLString safe for untrusted content?

Reference page
Short answer

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

RISKY
let html = "

\(untrustedText)

" webView.loadHTMLString(html, baseURL: nil)
SAFER
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

Is the deprecated UIWebView any different?

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.

Does `baseURL: nil` prevent XSS?

No. Apple documents `baseURL` for resolving relative URLs. It is not an HTML sanitizer, script switch, or sandbox guarantee.

Does `WKContentWorld` isolate the page DOM?

No. It separates JavaScript environments while they share the DOM. Treat DOM data and messages as untrusted, and authorize every native operation independently.

References

See also Cross-Site Scripting (XSS, CWE-79): How It Works and How to Prevent It in Every Language — flawopen.com Reflected vs. Stored vs. DOM-Based XSS Android addJavascriptInterface Security Risks Angular XSS Protection: Safe Defaults and Bypass APIs Content-Type Sniffing XSS: MIME Types and nosniff CSP vs. Output Escaping: Do You Need Both? Is React's dangerouslySetInnerHTML Safe?