Skip to content

Commit

Permalink
Merge branch 'main' into integrity-redo
Browse files Browse the repository at this point in the history
  • Loading branch information
robbiemc authored Aug 10, 2024
2 parents 8257831 + 35c579b commit 7ec37bf
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 22 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

This document proposes a way of building applications using web standard technologies that will have useful security properties unavailable to normal web pages. They are tentatively called Isolated Web Apps (IWAs). Rather than being hosted on live web servers and fetched over HTTPS, these applications are packaged into [Web Bundles](https://wpack-wg.github.io/bundled-responses/draft-ietf-wpack-bundled-responses.html), signed by their developer, and distributed to end-users through one or more of the potential methods described below.

Additional documents in this repo:
* [Permissions Explainer](./Permissions.md) describes `permissions_policy` manifest field and interaction with the `Permissions-Policy` header.
* [Scheme Explainer](./Scheme.md) describes the `isolated-app:` scheme and signed web bundlge IDs.
* [Updates Explainer](./Updates.md) describes the `version`, `update_manifest_url` manifest fields and updating process.
* [Isolated Contexts Specification](https://wicg.github.io/isolated-web-apps/isolated-contexts.html)

## Motivating Use Cases

Content Security Policy (CSP) provides strong protection against cross-site scripting (XSS) vulnerabilities. Transport Layer Security (TLS) and Subresource Integrity (SRI) provide protection against resources being tampered with in transit or when hosted on third-party servers. However, the threat model for some particularly security sensitive applications includes the main application server itself being compromised and serving malicious content. This goes beyond the protections that current policies can provide. An environment stricter than [[SECURE-CONTEXT]](https://w3c.github.io/webappsec-secure-contexts/) is therefore required.
Expand All @@ -22,7 +28,7 @@ The core of this proposal is making application updates explicit. Unlike TLS key

The reason for this is both practical and philosophical. If the identity of the site were still based on a DNS name, then it would still be vulnerable to a temporary loss of control over that domain or the infrastructure used to validate ownership of the domain. Philosophically, we also want to avoid building an alternative to certificate authorities which shares the same namespace. Isolated Web Apps therefore use a new scheme (tentatively, `isolated-app://`) where the authority section of the URL is based on the public key used to sign the Web Bundle containing the application resources. More details available in the [Scheme Explainer](./Scheme.md).

An application can be upgraded by replacing its Web Bundle with a new version signed by the same key. Since the key hash is the same, the application retains any local storage associated with the previous version. To prevent downgrade attacks, implementations may require either a `"version"` field in the [Web Application Manifest](https://www.w3.org/TR/appmanifest/), or the signature timestamp to be monotonically increasing.
An application can be upgraded by replacing its Web Bundle with a new version signed by the same key. Since the key hash is the same, the application retains any local storage associated with the previous version. To prevent downgrade attacks, implementations may require either a [`version`](./Updates.md) [Web Application Manifest](https://www.w3.org/TR/appmanifest/) field, or the signature timestamp to be monotonically increasing.

The protection against server compromise would be no good if the application could be tricked into loading malicious content from outside its Web Bundle, and so a rigorous Content Security Policy is applied,

Expand Down
2 changes: 1 addition & 1 deletion Updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ For example, a manifest hosted at `https://developer.example.com/app/updates.jso
{
"versions": [
{
"version:" "5.2.17",
"version": "5.2.17",
"src": "https://cdn.example.com/app-package-5.2.17.swbn"
},
{
Expand Down
56 changes: 36 additions & 20 deletions isolated-contexts.bs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ spec:webidl; type:dfn; text:namespace
urlPrefix: https://w3c.github.io/webappsec-csp/; spec:CSP3
type: abstract-op
text: Get fetch directive fallback list; url: #directive-fallback-list
urlPrefix: https://w3c.github.io/trusted-types/dist/spec/; spec:trusted-types
type: dfn
text: require-trusted-types-for-directive
</pre>
<pre class=biblio>
{
Expand Down Expand Up @@ -124,7 +127,8 @@ is the core entry point CSP will expose to HTML.
A [=CSP list=] |policies| is said to
<dfn for="CSP list" export local-lt="mitigate-injection">meaningfully
mitigate injection attacks</dfn> if the following algorithm returns
"`Meaningful`":
"`Meaningful`". Possible return values are "`Meaningful`" and
"`Not meaningful enough`".

<ol class="algorithm">
1. Let |meets object requirements|, |meets base requirements|,
Expand Down Expand Up @@ -190,7 +194,8 @@ the active directive</dfn> given a [=policy=] |policy| and a |directive name|:

<div algorithm="object requirements">
A [=policy=] |policy| <dfn for="policy">sufficiently mitigates plugins</dfn> if
the following algorithm returns "`Sufficient`":
the following algorithm returns "`Sufficient`". Possible return values are
"`Sufficient`" and "`Not sufficient`".

<ol class="algorithm">
1. <a abstract-op lt="obtain-directive">Obtain</a> |active directive| from
Expand All @@ -201,7 +206,8 @@ the following algorithm returns "`Sufficient`":
* |active directive| is not null
* |active directive|'s [=directive/value=]'s [=set/size=] is 1
* |active directive|'s [=directive/value=][0] is an
[=ASCII case-insensitive=] match for the string "`'none'`".
[=ASCII case-insensitive=] match for the string
"<a grammar>`'none'`</a>".

1. Return "`Not sufficient`".
</ol>
Expand All @@ -211,7 +217,8 @@ the following algorithm returns "`Sufficient`":

<div algorithm="base requirements">
A [=policy=] |policy| <dfn for="policy">sufficiently mitigates relative URL
manipulation</dfn> if the following algorithm returns "`Sufficient`":
manipulation</dfn> if the following algorithm returns "`Sufficient`".
Possible return values are "`Sufficient`" and "`Not sufficient`".

<ol class="algorithm">
1. [=For each=] |directive| in |policy|'s [=policy/directive set=]:
Expand All @@ -222,7 +229,7 @@ manipulation</dfn> if the following algorithm returns "`Sufficient`":
* |directive|'s [=directive/value=]'s [=set/size=] is 1
* |directive|'s [=directive/value=][0] is an
[=ASCII case-insensitive=] match for either the string
"`'none'`" or the string "`'self'`".
"<a grammar>`'none'`</a>" or the string "<a grammar>`'self'`</a>".

1. Return "`Not sufficient`".
</ol>
Expand All @@ -232,7 +239,8 @@ manipulation</dfn> if the following algorithm returns "`Sufficient`":

<div algorithm="script requirements">
A [=policy=] |policy| <dfn for="policy">sufficiently mitigates script execution</dfn>
if the following algorithm returns "`Sufficient`":
if the following algorithm returns "`Sufficient`".
Possible return values are "`Sufficient`" and "`Not sufficient`".

<ol class="algorithm">
1. <a abstract-op lt="obtain-directive">Obtain</a> |active directive| from
Expand All @@ -242,8 +250,9 @@ if the following algorithm returns "`Sufficient`":

* |active directive| is not null
* All [=source expressions=] in |active directive| are an
[=ASCII case-insensitive=] match for the strings "`'none'`",
"`'self'`", or "`'wasm-unsafe-eval'`".
[=ASCII case-insensitive=] match for the strings
"<a grammar>`'none'`</a>", "<a grammar>`'self'`</a>", or
"<a grammar>`'wasm-unsafe-eval'`</a>".

1. Return "`Not sufficient`".
</ol>
Expand All @@ -253,7 +262,8 @@ if the following algorithm returns "`Sufficient`":

<div algorithm="style requirements">
A [=policy=] |policy| <dfn for="policy">sufficiently mitigates style evaluation</dfn> if
the following algorithm returns "`Sufficient`":
the following algorithm returns "`Sufficient`".
Possible return values are "`Sufficient`" and "`Not sufficient`".

<ol class="algorithm">
1. [=For each=] |directive| in |policy|'s [=policy/directive set=]:
Expand All @@ -264,8 +274,9 @@ the following algorithm returns "`Sufficient`":

* |directive|'s [=directive/name=] is "`style-src`".
* All [=source expressions=] in |active directive| are an
[=ASCII case-insensitive=] match for the strings "`'none'`",
"`'self'`", or "`'unsafe-inline'`".
[=ASCII case-insensitive=] match for the strings
"<a grammar>`'none'`</a>", "<a grammar>`'self'`</a>", or
"<a grammar>`'unsafe-inline'`</a>".

1. Return "`Not sufficient`".
</ol>
Expand All @@ -275,18 +286,19 @@ the following algorithm returns "`Sufficient`":

<div algorithm="subresource requirements">
A [=policy=] |policy| <dfn for="policy">sufficiently blocks insecure
subresources</dfn> if the following algorithm returns "`Sufficient`":
subresources</dfn> if the following algorithm returns "`Sufficient`".
Possible return values are "`Sufficient`" and "`Not sufficient`".

<ol class="algorithm">
1. [=For each=] |directive name| in the set [`frame-src`, `connect-src`,
`img-src`, `media-src`, `font-src`]:
1. <a abstract-op lt="obtain-directive">Obtain</a> |active directive|
from |policy|, given |directive name|.

1. Return "`not sufficient`" if any [=source expression=] in
1. Return "`Not sufficient`" if any [=source expression=] in
|active directive| is **not** an [=ASCII case-insensitive=] match
for the strings "`'none'`", "`'self'`", "`https:`", "`blob:`",
or "`data:`".
for the strings "<a grammar>`'none'`</a>", "<a grammar>`'self'`</a>",
"`https:`", "`blob:`", or "`data:`".

1. Return "`Sufficient`"
</ol>
Expand All @@ -296,15 +308,17 @@ subresources</dfn> if the following algorithm returns "`Sufficient`":

<div algorithm="trusted type requirements">
A [=policy=] |policy| <dfn for="policy">sufficiently mitigates DOM sinks</dfn>
if the following algorithm returns "`Sufficient`":
if the following algorithm returns "`Sufficient`".
Possible return values are "`Sufficient`" and "`Not sufficient`".

<ol class="algorithm">
1. [=For each=] |directive| in |policy|'s [=policy/directive set=]:

1. Return "`Sufficient`" if all of the following are true:

* |directive|'s [=directive/name=] is
"`require-trusted-types-for`". [[!TRUSTED-TYPES]]
"<code>[=require-trusted-types-for-directive|require-trusted-types-for=]</code>".
[[!TRUSTED-TYPES]]
* |directive|'s [=directive/value=] [=set/contains=][0] an
[=ASCII case-insensitive=] match for the string "`'script'`".

Expand Down Expand Up @@ -338,7 +352,8 @@ require-trusted-types-for 'script';
A [=CSP list=] |policies| is said to
<dfn for="CSP list" export local-lt="mitigate-ui-redressing">meaningfully
mitigate UI Redressing attacks</dfn> [[UISECURITY]] if the following algorithm
returns "`Meaningful`":
returns "`Meaningful`".
Possible return values are "`Meaningful`" and "`Not meaningful enough`".

<ol class="algorithm">
1. [=For each=] |policy| in |policies|:
Expand All @@ -355,7 +370,7 @@ returns "`Meaningful`":
* |directive|'s [=directive/value=]'s [=set/size=] is 1
* |directive|'s [=directive/value=][0] is an
[=ASCII case-insensitive=] match for either the string
"`'none'`" or the string "`'self'`".
"<a grammar>`'none'`</a>" or the string "<a grammar>`'self'`</a>".

1. Return "`Not meaningful enough`".
</ol>
Expand Down Expand Up @@ -438,7 +453,8 @@ In Fetch, we'll use the [=integrity verification algorithm=] defined in
### Verify the integrity of a response ### {#fetch-verify-response}
<div algorithm>
To <dfn>verify the integrity of a response</dfn> given a [=request=] |request|
and a [=response=] |response|:
and a [=response=] |response|, run these steps. Possible return values are
"`not applicable`", "`invalid`", or "`valid`".

<ol>
<li>Let |client| be |request|'s [=request/client=].</li>
Expand Down

0 comments on commit 7ec37bf

Please sign in to comment.