Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions .github/workflows/pr.yml

This file was deleted.

68 changes: 68 additions & 0 deletions diagrams/WebView-Basic.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<mxfile host="app.diagrams.net">
<diagram name="Seite-1" id="UvmskQSb0NUUPCfxTzRg">
<mxGraphModel dx="1521" dy="856" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="_1olbHYe64u3RBr8zlPl-3" parent="1" style="rounded=0;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="560" width="750" x="420" y="130" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-5" parent="1" style="rounded=0;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="390" width="680" x="460" y="270" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-6" parent="1" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;" value="" vertex="1">
<mxGeometry height="200" width="610" x="490" y="440" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-7" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="Host App" vertex="1">
<mxGeometry height="30" width="60" x="450" y="200" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-8" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="WebView" vertex="1">
<mxGeometry height="30" width="60" x="490" y="290" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-9" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="&lt;div&gt;Origin&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Web Content&lt;/div&gt;" vertex="1">
<mxGeometry height="30" width="180" x="710" y="540" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-10" parent="1" style="sketch=0;aspect=fixed;pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=light-dark(#6F0000, #a51d2d);labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;fillColor=#a20025;shape=mxgraph.azure.script_file;fontColor=#ffffff;" value="" vertex="1">
<mxGeometry height="50" width="47" x="950" y="160" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-11" edge="1" parent="1" source="_1olbHYe64u3RBr8zlPl-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.827;entryY=0.044;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=openThin;startFill=0;fillColor=#a20025;strokeColor=light-dark(#000000,#FF0000);" target="_1olbHYe64u3RBr8zlPl-6">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="994" y="295" />
<mxPoint x="995" y="295" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-13" connectable="0" parent="_1olbHYe64u3RBr8zlPl-11" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" value="JavaScript Bridge" vertex="1">
<mxGeometry relative="1" x="0.1534" y="1" as="geometry">
<mxPoint y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-14" parent="1" style="shape=callout;whiteSpace=wrap;html=1;perimeter=calloutPerimeter;size=40;position=0.5;" value="Permissions" vertex="1">
<mxGeometry height="60" width="90" x="795" y="160" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-16" edge="1" parent="1" source="_1olbHYe64u3RBr8zlPl-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0;exitDx=45;exitDy=59.99999999999999;exitPerimeter=0;entryX=0.558;entryY=0.008;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=light-dark(#000000,#FF0000);startArrow=classic;startFill=1;" target="_1olbHYe64u3RBr8zlPl-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-17" parent="1" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" value="Storage" vertex="1">
<mxGeometry height="80" width="60" x="680" y="140" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-19" edge="1" parent="1" source="_1olbHYe64u3RBr8zlPl-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;innerLoopWaypoints=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" target="_1olbHYe64u3RBr8zlPl-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-23" edge="1" parent="1" source="_1olbHYe64u3RBr8zlPl-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.368;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" target="_1olbHYe64u3RBr8zlPl-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-26" edge="1" parent="1" source="_1olbHYe64u3RBr8zlPl-24" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;" target="_1olbHYe64u3RBr8zlPl-17" value="">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-24" parent="1" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" value="Storage" vertex="1">
<mxGeometry height="80" width="60" x="680" y="310" as="geometry" />
</mxCell>
<mxCell id="_1olbHYe64u3RBr8zlPl-25" edge="1" parent="1" source="_1olbHYe64u3RBr8zlPl-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.36;entryY=0.017;entryDx=0;entryDy=0;entryPerimeter=0;" target="_1olbHYe64u3RBr8zlPl-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
4 changes: 4 additions & 0 deletions diagrams/WebView-Basic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
151 changes: 131 additions & 20 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,24 @@ Abstract:
Documention on how WebViews diverge conceptually from security concepts,
user agent duties and practices defined for browsers.
Markup Shorthands: markdown yes
Boilerplate: conformance no
Status Text:
This report was published by the [WebView Community Group](https://www.w3.org/community/webview/). It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the [W3C Community Contributor License Agreement (CLA)](https://www.w3.org/community/about/agreements/cla/) there is a limited opt-out and other conditions apply. Learn more about [W3C Community and Business Groups](https://www.w3.org/community/).

This is a living document and does not intend to be exhaustive.

GitHub Issues are preferred for discussion of this report.
</pre>

<pre class="biblio">
{
"USAGE-AND-CHALLENGES": {
"authors": ["WebView Community Group"],
"href": "https://webview-cg.github.io/usage-and-challenges",
"title": "WebView: Usage Scenarios and Challenges",
"status": "Draft Community Group Report"
}
}
</pre>


Expand All @@ -28,31 +46,49 @@ This report documents how WebViews diverge conceptually from security concepts,

# Rationale # {#rationale}

The TAG Web User Agents Finding states the key claim for user agents as software components :
The [[web-user-agents inline]] finding by the [TAG](https://tag.w3.org/) states the key claim for user agents as software components :

> WebView libraries are *not* user agents on their own and do not implement the user-agent duties;
> the **embedding application inherits the duties if it acts as a user agent**, and "developers need to take extra care … when using a non-user-agent WebView to implement an in-app browser."

It does not say *how*. This document is the cross-vendor, mechanism-level account of how a WebView configuration causes the embedding app to succeed or fail at each duty.
It does not say *how*. This document is the mechanism-level account of how a WebView configuration causes the embedding app to succeed or fail at each duty.

# Scenario / Configuration # {#configuration}

WebViews can be used in many different ways but one very typical configuration has the most security critical consequences.

**A host app embeds web content and exposes a native bridge.**

Note: TODO Details
<div class="example" id="example-config" heading="Configrations">

<ul>
<li>A hybrid app using a framework like Capacitor, Cordova or Tauri</li>
<li>A super app using a WebView to provide MiniApps</li>
</ul>

</div>

# Terminology # {#terminology}

<div class="informative">

* Host app
* [[USAGE-AND-CHALLENGES#webviews|WebViews]]
* [[USAGE-AND-CHALLENGES#types-of-webviews|Types of WebViews]]

</div>

# Diagrams # {#diagrams}

Note: TODO: Basic diagram in preparation for threat model, Use the DSL?
Note: TODO: More diagrams in preparation for threat model.

<pre class=railroad>
T: /*
ZeroOrMore:
N: anything but * followed by /
T: */
</pre>
<figure id="fig-hostapp-webview-origin">

<img src="diagrams/WebView-Basic.svg" alt="The host app contains the WebView, which contains the origin's web content. The host app reaches into the origin via a JavaScript bridge, and also mediates permissions requested by the origin.">

<figcaption>The host app can inject script into the origin loaded in the WebView via a native bridge, crossing a boundary that browsers otherwise protect.</figcaption>

</figure>


# Duties # {#duties}
Expand All @@ -66,13 +102,71 @@ Looking at the duties, design principles and threat model we can list areas wher
If users have a realistic expectation of safety, they can make informed decisions between Web-based technologies and other technologies.
For example, users may choose to use a web-based food ordering page, rather than installing an app, since installing a native app is riskier than visiting a web page.

* **Host control over content (integrity)**
* **Same Origin Policy**
* **Sandbox / process isolation**
* **Transport**: TLS, mixed content
* **Permissions**
* **Storage**
* **Anti-Tracking**
### Host control over content (integrity) ### {#host-control-over-content}

The host app can intercept and sometime rewrite requests and responses in the WebView.
WebViews sometimes also can register their own custom schemes.

<div class="example" id="example-host-control" heading="HTTP Intercept">

<table>
<thead>
<tr>
<th>Platform</th>
<th>API</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Android</td>
<td>WebViewAssetLoader</td>
<td></td>
</tr>
<tr>
<td>iOS, macOS</td>
<td>WKURLSchemeHandler</td>
<td></td>
</tr>
</tbody>
</table>

</div>

### Same Origin Policy ### {#same-origin-policy}

WebView APIs let the host app inject and execute JavaScript and CSS into an site regardless of the origin policy.

### Sandbox / process isolation ### {#sandbox-process-isolation}

Issue(#2): How does sandboxing and process isolation work in WebViews?

### Transport: TLS, mixed content ### {#transport}

The host app can change TLS settings without the user noticing.

### Permissions ### {#permissions}

Web permissions like location are handled by the host app and not through user interfaces provided by the browser.
The host app can silently allow or dismiss permission requests from web pages.

### Storage ### {#storage}

<div class="informative">

[[USAGE-AND-CHALLENGES#dfn-browser-like|Browser-like WebViews]] usually share their state with the systems browser.

[[USAGE-AND-CHALLENGES#dfn-fully-fledged|Fully-fledged WebViews]] usually have their own storage scoped to the app.

</div>

WebViews provide APIs to create "CookieStores" that let the host app developer decide how state is shared between WebView instances.

### Anti-Tracking ### {#anti-tracking}

The user has usually no way to configure anti-tracking measures. The host app might or might not be able to handle anti-tracking.
So there is no transparency to the user if their browsing is protected by anti-tracking technology.
WebViews have no UI to inspect how cookies are blocked.

## Honesty ## {#honesty}

Expand All @@ -82,9 +176,26 @@ Users depend on trusted user interfaces such as the address bar, security indica
to understand who they are interacting with and how.
These trusted user interfaces must be able to be designed in a way that enables users to trust and verify that the information they provide is genuine, and hasn’t been spoofed or hijacked by the website.

* **Trusted UI / visible origin**
* **Security/permission indicators**
### Trusted UI / visible origin ### {#trustedui}

The user usually cannot see the origin and TLS status in full screen WebViews.

### Security/permission indicators ### {#permission-indicators}

The host app has control of permission prompts or UI if elevated privilegdes are used.

<div class="example" id="example-oauth" heading="OAuth">
Using a WebView where the host app can intervene for a OAuth flow is discouraged
</div>

# Comparison Table # {#comparison}

Issue(#1): Compare WebView implementations and show examples
Issue(#1): Should we add WebView implementations and show examples?

# Best practices # {#best-practices}

Practical advice to follow when using WebViews.

## Pick the correct type ## {#type}

No OAuth
Loading