W3C home > Mailing lists > Public > public-webappsec@w3.org > April 2019

Re: characterizing framing security needs for webappsec consideration

From: Ian Clelland <iclelland@google.com>
Date: Wed, 17 Apr 2019 01:08:21 -0400
Message-ID: <CAK_TSXKjEhh4Uj7WXzdBh_KEX3n21zwp0LEaucw49e3-tF4YZg@mail.gmail.com>
To: Jeff Hodges <jdhodges@google.com>
Cc: Rouslan Solomakhin <rouslan@google.com>, Web Application Security Working Group <public-webappsec@w3.org>
Hi Jeff,

PaymentRequest was actually one of the very first features to utilize
Feature Policy in Chrome -- by design, it should be able to handle allowing
and restricting that API in same- and cross-origin embedding scenarios.
I've added more detailed comments inline, but the shortest answer is that
this *should* all work the way Rouslan has described, and that yes, we may
need to add something to the spec if we want to *require* an opt-in from
the embedded page.

On Tue, Apr 16, 2019 at 8:56 PM Jeff Hodges <jdhodges@google.com> wrote:

> HI WebAppSec folk,
> I've been corresponding with Rouslan over in the Web Payments working
> group regarding Feature Policy in cross-origin iFrames and sandboxed
> iFrames and how they might be used for a couple of use cases he/they have.
> It would seem to have relevance for the still-to-be addressed question of
> policies wrt WebAuthn in cross-origin iFrames.
> This is kinda long, but this stuff is complex. I'll try adding it to the
> end of the agenda for tomorrow's call...
> On Tue, Apr 16, 2019 at 6:52 AM Rouslan Solomakhin <rouslan@google.com>
> wrote:
>> Thank you for the reply, Jeff! Please see my comments inline.
>> On Mon, Apr 15, 2019 at 9:46 PM Jeff Hodges <jdhodges@google.com> wrote:
>>> On Wed, Apr 3, 2019 at 5:31 PM Rouslan Solomakhin <rouslan@google.com>
>>> wrote:
>>>> Here's a summary of the needs/considerations for the Web Payment APIs:
>>>> *#1: Would it be possible to disable certain powerful APIs (e.g.,
>>>> Payment Request and Payment Handler) in embedded cross-origin iframes by
>>>> default, unless the embedded iframe explicitly allows to be embedded for
>>>> the purpose of payments?* Concretely, this could be something like a <meta
>>>> allow-when-embedded="payments"> tag, for example.
>>> *In my reading of Feature Policy
>>> <https://w3c.github.io/webappsec-feature-policy/>, it seems this use case
>>> is addressed*.  For embedding origin example-embedding.foo, and
>>> embedded origin example-embedded.bar, the embedding webapp would
>>> declare on the embedded iframe:
>>> `<iframe allow="payment example-embedded.bar" ...>`
>>> and example-embedded.bar would return a "header policy" (from which the
>>> UA forms the embedded content's "declared policy"), like so:
>>> `Feature-Policy: payment 'self';`
>>> And then the magic Feature Policy algorithm Is feature enabled in
>>> document for origin
>>> <https://w3c.github.io/webappsec-feature-policy/#algo-is-feature-enabled>
>>>  combines the two policy declarations and comes up with "Enabled" for
>>> the "payment" feature in the cross-origin iframe.
>> Is my understanding correct that example-embedded.bar does not have to
>> specify a "header policy" for payments to work?
> I *think* the answer is "no" because this use case is explicitly
> cross-origin (however, see below).  I think the answer is "yes" if it were
> a same-origin use case.

As currently specced, Feature Policy does *not* require
example-embedded.bar to declare a policy through HTTP headers in order to
use PaymentRequest. If PaymentRequest is allowed in the embedding document
by its own feature policy, and it uses an iframe tag like the one above,
then it will also be allowed in the embedded document.

By the spec, when the embedded document is created, we will define an
inherited policy for it, using the embedding document's policy and the
container policy constructed from the iframe element. In this case, the
inherited policy for the "payment" feature will be Enabled. Without a
Feature-Policy header, the embedded document's policy will not have a
declared policy for the "payment" feature.

With that policy in place, when the embedded document tries to use
PaymentRequest, it should call Is feature enabled in document for origin
with its own document and its own origin as arguments. Because the
inherited policy is "Enabled", and the feature is *not* present in the
declared policy, that algorithm will fall through to step 5, discover that
"origin" is same origin-domain with document's origin (the origins should
be identical because of how it was called), and return True.

> So, upon further grovelling thru the Feature Policy spec, I am unsure
> whether it can be employed to allow cross-origin feature use. The spec
> seems unclear whether the Should request be allowed to use feature
> <https://w3c.github.io/webappsec-feature-policy/#algo-should-request-be-allowed-to-use-feature> alg
> is invoked in the case where JS running in the embedded frame invokes
> PaymentRequest ?

I'm not sure which spec you mean when you say that it is unclear -- I'll
explain the specs as I understand the relationship, but I'd be happy to
make changes where I can to make it clearer:

The Payment Request API spec says that the PaymentRequest constructor
<https://www.w3.org/TR/payment-request/#constructor> should call HTML's
"allowed to use" algorithm with the current document. That algorithm
what calls Is feature enabled in document for origin
and it always calls it with the document and the document's own origin, so
the same-origin check should always be true (when called from HTML).

>   The Is feature enabled in document for origin
> <https://w3c.github.io/webappsec-feature-policy/#algo-is-feature-enabled>
> alg, which does the combining of inherited, declared, and default policies,
> appears to only be called from the former alg.

It's also called from Define an inherited policy for feature in container
at origin
but more importantly, it's called from HTML: it's an exported algorithm
that can be used as an entry point into Feature Policy from other specs.

>   Also, if the *document* that is passed to the latter alg is the
> top-level document, then the embedded document's declared policy (if any)
> is not evaluated by the latter alg. And so this scenario would not work.  :(

Generally, the document passed to Is feature enabled in document for origin
<https://w3c.github.io/webappsec-feature-policy/#algo-is-feature-enabled>, when
used to answer "can a document use this feature?", is the document which is
trying to use the feature, not the top-level doc.

> If this is correct, then I am proposing that we make an exception for
>> "payment" specifically to always require the "header policy" in the
>> embedded iframe. This would be a change in the spec and, therefore,
>> implementations, if I understand correctly.
We have discussed the idea that some features need an explicit opt-in from
the embedded site in order to be *disabled*  -- this turns out to be
important when disabling existing functionality; I don't know if anyone has
considered requiring the same opt-in for *enabling* a feature. My belief
has always been that if the embedding document is trusted to use the
feature, then it should be able to delegate that to the documents that it
embeds (if it trusts them as well). Are you suggesting that use of
PaymentRequest should also require such an opt-in from the *embedded

> In any case, regardless whether Feature Policy is actually intended to
> support the above feeble cross-origin example (this is not made clear in
> the spec, ISTM), I am now guessing that the above example "header policy"
> (i.e., Feature-Policy header field) ought to perhaps be:
> `Feature-Policy: payment example-embedding.foo;`
> ..and am wondering whether that would be a reasonable way for the
> combination of the embedding and embedded parties to explicitly declare
> that such cross-origin use of a feature(s) is allowed?  (this must have
> already been discussed ?)
>> #2: Would it be possible to disable these powerful APIs in all iframes
>>>> that are not sandboxed? Cross origin iframes today have to look like this:
>>>> <iframe allow="payments" src="https://payment-app.com/some.js"></iframe>,
>>>> if the parent iframe wants to allow payments in the child iframe. Would it
>>>> be kosher to require the tag to look like this: <iframe *sandbox*
>>>> allow="payments" src="https://payment-app.com/some.js" ></iframe> ?
>>> Sandbox attribute is defined here
>>> <https://html.spec.whatwg.org/multipage/iframe-embed-object.html#attr-iframe-sandbox>
>>> .
>>> Given that definition, it seems that the sandbox attr does not match
>>> your above use case. The sandbox attr is about protecting the embedding
>>> webapp from the framed webapp/content (and not vice-versa), and also not
>>> about controlling whether powerful features are enabled or not (the latter
>>> is the province of Feature Policy).
>>> That said however, it may be overall reasonable standard best practice
>>> for embedders to declare many iframes (in general) like so:
>>> <iframe sandbox="allow-same-origin allow-forms allow-scripts" src="
>>> https://maps.example.com/embedded.html"></iframe>
>>> ..because it disables plugins and popups, thus reducing the risk of the
>>> user being exposed to malware and other annoyances.
>> It feels like a payment sheet can fall into the category of "other
>> annoyances."
> Possibly?
>> I am proposing to change the spec to say: "if the cross-origin iframe
>> does not have a sandbox attribute, then disable the payment APIs in that
>> iframe." Does that sound reasonable?
> By spec, you're referring to the Payment Request spec?
> I remain uncertain that requiring the sandbox attr is appropriate.
> However, the framed webapp is able to escape the sandbox relatively
>>> easily. See examples and warnings in Sandbox attribute definition
>>> <https://html.spec.whatwg.org/multipage/iframe-embed-object.html#attr-iframe-sandbox>
>>> .
>> Is my reading of the spec correct that only iframes from the same origin
>> as the embedder can escape sandbox?
> That seems to be implied?
> HTH,
> =JeffH
Received on Wednesday, 17 April 2019 05:08:58 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 18:55:06 UTC