Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wildcards in Permissions Policy Origins #482

Closed
wants to merge 18 commits into from
71 changes: 58 additions & 13 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ Markup Shorthands: css no, markdown yes
</pre>
<pre class="link-defaults">
spec:dom; type:interface; for:/; text:Document
spec:html; type:dfn; for:/; text:origin
spec:fetch; type:dfn; for:Response; text:response
spec:html; type:dfn; for:/; text:browsing context
spec:html; type:element; text:script
Expand Down Expand Up @@ -129,6 +128,27 @@ spec: HEADER-STRUCTURE; urlPrefix: https://httpwg.org/http-extensions/draft-ietf
those frames hosting content from http://example.com or SecureCorp itself
will actually be granted the ability to use that API.</p>
</div>
<div class="example">
<p>SecureCorp Inc. restructured its domains and now needs to needs to delegate
use of the Geolocation API to its origin ("<code>https://example.com</code>")
as well as three subdomains ("<code>https://geo.example.com</code>",
"<code>https://geo2.example.com</code>", and "<code>https://new.geo2.example.com</code>").
This needs to be accomplished while still disabling the use of the Geolocation API
within all other browsing contexts. It can do this by delivering the following HTTP response header:</p>
<pre>
<a http-header>Permissions-Policy</a>: geolocation=(self "https://example.com" "https://geo.example.com" "https://geo2.example.com" "https://new.geo2.example.com")
</pre>
<p>This works, but if SecureCorp Inc. feels safe delegating to any subdomains on
"<code>https://example.com</code>" the HTTP response header could instead be:</p>
<pre>
<a http-header>Permissions-Policy</a>: geolocation=(self "https://example.com" "https://*.example.com")
</pre>
<p>Not only would the above header permit "<code>https://geo.example.com</code>",
"<code>https://geo2.example.com</code>", and "<code>https://new.geo2.example.com</code>"
to use the Geolocation API, but any other subdomains of "<code>https://example.com</code>"
could use it too. Note that "<code>https://example.com</code>" is not covered by the
<a>allowlist</a> entry "<code>https://*.example.com</code>" and must also be added.</p>
</div>
</section>
<section>
<h2 id="other-and-related-mechanisms">Other and related mechanisms</h2>
Expand Down Expand Up @@ -280,7 +300,8 @@ spec: HEADER-STRUCTURE; urlPrefix: https://httpwg.org/http-extensions/draft-ietf
<ul>
<li><dfn>The special value <code>*</code></dfn>, which represents every
origin, or</li>
<li>An <a>ordered set</a> of [=origins=]</li>
<li>An <a>ordered set</a> of tuples containing an [=origin=] and a boolean
indicating whether or not a wildcard subdomain was present.</li>
</ul>
<div class="note">
The keywords <code>'self'</code>, <code>'src'</code>, and
Expand All @@ -297,8 +318,25 @@ spec: HEADER-STRUCTURE; urlPrefix: https://httpwg.org/http-extensions/draft-ietf
then return true.</li>
<li>Otherwise, for each <var>item</var> in the <a>allowlist</a>:
<ol>
<li>If <var>item</var> is [=same origin-domain=] with
<var>origin</var>, then return true.</li>
<li>If <var>item</var> is a tuple of an [=origin=] that's [=same origin-domain=]
with <var>origin</var> and the boolean <code>False</code>, then return true.</li>
<li>Else if <var>item</var> is a tuple of a <a>serialized-origin</a> that's not [=same origin-domain=]
with <var>origin</var> and the boolean <code>True</code>, then:</li>
arichiv marked this conversation as resolved.
Show resolved Hide resolved
<ol>
<li>If <var>origin</var> is not a <a>tuple origin</a>, then return false.<li>
<li>If <var>origin</var>'s <a>host</a> has a null <a>registrable domain</a>, return false.<li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to refer to the host of an origin using the for attribute.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain how you resolved this, as far as I can tell you reordered the words, but that doesn't help the fact that host points to the wrong thing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I had misunderstood, is it correct now?

<li>Set <var>originWithoutWildcard</var> to be equal to the first value of the tuple <var>item</var>.</li>
<li>Set <var>originCandidate</var> to be equal to <var>origin</var> with the sequence
of <a>code points</a> in the <a>host</a> from the start up to and including the first "." removed.</li>
<li>While <var>originCandidate</var> has a <a>host</a> with a non-nill <a>registrable domain</a>:</li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same problem with the host field as above.

Also, it's non-null.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

<ol>
<li>If <var>originWithoutWildcard</var> is [=same origin-domain=] </li> with
arichiv marked this conversation as resolved.
Show resolved Hide resolved
<var>originCandidate</var>, then return true.</li>
<li>Set <var>originCandidate</var> to be equal to <var>originCandidate</var> with the sequence
of <a>code points</a> in the <a>host</a> from the start up to and including the first "." removed.</li>
</ol>
<li>return false.</li>
</ol>
</ol>
</li>
<li>return false.</li>
Expand Down Expand Up @@ -338,13 +376,16 @@ spec: HEADER-STRUCTURE; urlPrefix: https://httpwg.org/http-extensions/draft-ietf
<dfn>serialized-policy-directive</dfn> = <a>feature-identifier</a> RWS <a>allow-list</a>
<dfn>feature-identifier</dfn> = 1*( ALPHA / DIGIT / "-")
<dfn>allow-list</dfn> = <a>allow-list-value</a> *(RWS <a>allow-list-value</a>)
<dfn>allow-list-value</dfn> = <a>serialized-origin</a> / "*" / "'self'" / "'src'" / "'none'"
<dfn>allow-list-value</dfn> = <a>serialized-origin</a> / <a>serialized-origin-with-wildcard-subdomain</a> / "*" / "'self'" / "'src'" / "'none'"
</pre>
<p><dfn><code>serialized-origin</code></dfn> is the
<a>serialization of an origin</a>. However, the code points U+0027 ('),
U+0021 (*), U+002C (,) and U+003B (;) MUST NOT appear in the serialization.
If they are required, they must be percent-encoded as "`%27`", "`%2A`",
"`%2C`" or "`%3B`", respectively.</p>
<p><dfn><code>serialized-origin-with-wildcard-subdomain</code></dfn> is a serialization of a
<a>tuple origin</a> whose <a>tuple</a>'s <a>host</a> is a <a>domain</a>, has a non-null
<a>registrable domain</a>, and is <a>prefixed</a> by the string "*.".</p>
<div class="note">
The string "<code>'self'</code>" may be used as an origin in an allowlist.
When it is used in this way, it will refer to the origin of the document
Expand Down Expand Up @@ -775,16 +816,17 @@ partial interface HTMLIFrameElement {
<code>*</code></a>.
1. Otherwise:
1. Set |allowlist| to an new <a>ordered set</a>.
1. If |value| is the token `self`, append |origin| to |allowlist|.
1. If |value| is the token `self`, append (|origin|, <code>False</code>) to |allowlist|.
1. If |value| is a list, then for each |element| in |value|:
1. If |element| is the token `self`, append |origin| to
|allowlist|.
1. Otherwise, let |result| be the result of executing the <a>URL
parser</a> on |element|.
1. If |element| is the token `self`, append (|origin|, <code>False</code>) to |allowlist|.
1. Otherwise, set |hasWildcardSubdomain| to <code>False</code>.
1. If |element| is a <a>serialized-origin-with-wildcard-subdomain</a>, then:
1. Set |hasWildcardSubdomain| to <code>True</code>
1. Set |element| to |element| with the sequence of <a>code points</a> "*." removed at the start of the <a>host</a>.
1. Let |result| be the result of executing the <a>URL parser</a> on |element|.
1. If |result| is not failure:
1. Let |target| be the origin of |result|.
1. If |target| is not an opaque origin, append |target| to
|allowlist|.
1. If |target| is not an opaque origin, append (|target|, |hasWildcardSubdomain|) to |allowlist|.
1. Set |policy|[|feature|] to |allowlist|.
1. Return |policy|.

Expand Down Expand Up @@ -828,12 +870,15 @@ partial interface HTMLIFrameElement {
parser</a> on |element|.
1. If |result| is not failure:
1. Let |target| be the origin of |result|.
1. If |target| is not an opaque origin, append |target| to
1. If |target| is not an opaque origin, append (|target|, <code>False</code>) to
|allowlist|.
1. Set |directive|[|feature|] to |allowlist|.
1. Return |directive|

</div>

Note: This algorithm does not support wildcard subdomains in allowlists. It might be allowed in future, but the
security implications have not yet been reviewed.
</section>
<section>
## <dfn export abstract-op id="process-policy-attributes">Process permissions policy attributes</dfn> ## {#algo-process-policy-attributes}
Expand Down