WebView-CG / usage-and-challenges

Documenting usage scenarios for WebView and the challenges they create
https://webview-cg.github.io/usage-and-challenges/
Other
12 stars 4 forks source link

Display and manipulate third party content while blocking third party scripting #16

Open bduga opened 2 years ago

bduga commented 2 years ago

Use case name

Display and manipulate third party content securely

Submitter(s)

Brady Duga

Motivation

In the ebook publishing world web technologies are used to present digital publications with rich styling and extensive user configuration (fonts, font sizes, margins, line spacing, colors, etc). This often means using a webview to display content, but the content itself can come from a number of sources (purchased through the ereader, purchased elsewhere, discovered on the internet), which should all be considered untrusted. The application then needs a mechanism to adjust elements of the content in a secure way, for instance changing the font used or altering the text/background colors. This is often done by enabling scripts in the webview to allow application-injected scripts to run, but which has the side effect of allowing third party scripts to run.

Stakeholders

Digital publishers Anyone who uses WebView as a display engine for declarative content (html + css + other declarative technologies)

Analysis

Current APIs (injected javascript) provide a very powerful way of modifying content, however enabling third party scripts in webview is a significant attack vector and it can take significant work to reduce the risk of such attacks and essentially impossible to completely eliminate them.

In order to avoid opening the attack vector at all, it seems there are two broad possibilities: either provide a way to disable certain scripts while allowing others (for instance, block scripts in content, but not injected scripts), or provide a non-script based mechanism to manipulate the content of the webview from the containing application.

Related W3C deliverables and/or work items

How is the issue solved in the Browser, and what’s more is needed?

It is not clear this is solved in the Browser. Similar problems can happen in the browser for third party content that comes from a trusted origin, though manipulating content in a frame is more restrictive than manipulating content in a webview.

dontcallmedom commented 2 years ago

https://www.w3.org/TR/CSP3/ likely provides a path to filter what scripts can run - this probably depends on having a well-defined origin for local content per #7

bduga commented 2 years ago

CSP does provide a solution here, and is roughly my first option in the analysis section, but it still (probably) requires some changes to webviews, or at least a standardization on APIs (and some clarity). Take this example, assuming Android WebView (picking on that since I know it better than the others):

Given this content:

<html>
  ...
  <script> doBadStuff() </script>
  ...

I then want to do something from the App layer, maybe find the word at a specific location:

webView.evaluateJavascript("findWord($x, $y)", someCallback)

What are the sources of these two scripts? I think they are both self (based on a quick conversation with @rayankans ), but that isn't really documented. And in that case I still can't forbid one and allow the other. There may be better solutions with webmessage posting, but it is not clear to me what the source of the injected JS from WebViewCompat#addWebMessageListener is (and again, Android only). So while CSP may be the correct solution, there is still work to do to enable this use case beyond a well defined origin, at least as far as I can tell.

dontcallmedom commented 2 years ago

I think the injected vs pre-existing scripts could be distinguished by relying on the nonce attribute that would be enforced via CSP.

In other words, as the developer, you would set your CSP to enforce a nonce of your choice, and you would inject scripts with the nonce attribute set to the value.

bduga commented 2 years ago

That is an interesting approach, and probably worth considering as a solution, but I am still not sure how to set the nonce on something like evaluateJavascript, since that is effectively an inline script (I think, again not well defined), but there is no script tag to hang an attribute on. And it also requires evaluating the APIs of all webviews to see if there is a consistent solution.