Skip to content

WKWebView navigation and security considerations

Garvan Keeley edited this page Jul 24, 2020 · 2 revisions

Detecting Navigations

WKWebView navigations trigger the following:

  • func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!)
  • func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!)
  • webView.url KVO change

For security reasons it is critical not to update the displayed URL in the URL bar until the old html document is destroyed and the new one created (alternatively it could be said the JS context of the old page must be destroyed and a new one created). A common spoofing attack is to trick the browser to change the displayed URL and use JS to change the displayed page to a spoofed page.

The didStartProvisionalNavigation happens too early to be used safely, only didCommit happens at the correct time.

Single Page JS Apps (SPAs)

Sites such as youtube.com use JS frameworks that navigate purely by XHR requests to change the document body without navigating; they create the appearance of navigating by pushing URLs to the browser history using window.history.pushState. In WKWebView, these do not trigger any traditional navigational events:

  • JS events not called: onload, hashchange, DOMContentLoaded, document readystatechange
  • no WKWebView delegates get called

Fortunately WKWebView.url KVO catches the change in the URL for the page. It is considered safe to update the displayed URL for navigations within an origin as spoofing attacks are not currently known to able to exploit that (see the 'same origin policy' link below). It is worth noting there is a cross-origin restriction on the history.pushState function also. Therefore if the webpage URL changes but the origin is unchanged, it is safe to update the displayed URL in this case. In any other case, only didCommit should be used.

See also:

Clone this wiki locally