[go: nahoru, domu]

Autofill across iframes

Chrome Autofill fills in frame-transcending forms like the following pseudo-code example.

<!-- Top-level document URL: https://merchant.example/... -->
<form>
  Cardholder name:    <input id="name">
  Credit card number: <iframe src="https://psp.example/..." allow="shared-autofill"><input id="num"></iframe>
  Expiration date:    <input id="exp">
  CVC:                <iframe src="https://psp.example/..." allow="shared-autofill"><input id="cvc"></iframe>
                      <iframe src="https://ads.example/..."><input id="account"></iframe>
</form>

This applies to address and payment information, but not to passwords.

The security policy

An autofill fills a form control candidate only if one of the following is true:

  • the autofill's origin and the candidate's origin are the same origin;
  • shared-autofill is enabled in the candidate's node document and one of the following is true:
    • the autofill's origin and the top-level origin are the same origin;
    • the candidate's origin and the top-level origin are the same origin and the candidate's autofill value is non-sensitive.

The terminology used above is defined in the appendix.

This policy is the eligibility for autofill definition plus the additional “... and one of the following is true” conjunct in the shared-autofill clause.

The policy is implemented in FormForest::GetRendererFormsOfBrowserForm().

The rationale

The example form above exhibits a common pattern: at the time of writing, about 20% of the payment forms on the web span multiple origins. Most commonly, the cardholder name field's origin is the top-level origin, whereas the credit card number is in a cross-origin iframe hosted by the payment service provider (PSP).

These iframes are typically styled so that they seamlessly integrate with the merchant‘s page -- the user is not made aware that multiple frames and origins are involved. Yet the different origins isolate the payment information from the merchant’s website, which helps them comply with the payment card industry's data security standard (see Section 2.2.3 of the PCI-DSS best practices).

Chrome Autofill's objective is to fill fields that the user expects to be filled, even if those fields cross origins, while protecting the user against possibly malicious sub-frames. Intuitively, we support two “directions”:

  • “Downwards”: An autofill may fill fields in descendant documents where shared-autofill is enabled. In our example, an autofill initiated on the cardholder name field may fill the credit card number field.
  • “Upwards”: An autofill may fill certain values in ancestor documents. In our example, an autofill initiated on the credit card number field may fill the cardholder name field.

We restrict the values that may be filled “upwards” especially to prevent leaking sensitive payment information -- credit card numbers and CVCs that the PCI-DSS intends to protect -- into the merchant's page. The “non-sensitive” values that we allow to be filled “upwards” are credit card types, cardholder names, and expiration dates.

The terms “upwards” and “downwards” are imprecise: our security policy doesn't refer to the top-level traversable's node document, but rather to its origin, the top-level origin. This way, Autofill works the same when, for example, the cardholder name is hosted in a same-origin iframe: <iframe src="https://merchant.example/..."><input id="name"></iframe>.

Our security policy does not allow “upwards” or “downwards” filling to and from arbitrary documents. It only allows filling “upwards to” main-origin documents and “downwards from” main-origin documents. This simplifies reasoning about the security policy as well as the implementation, and is still sufficient for real-world payment forms.

The following table illustrates which fields may be filled in our example form depending on the autofill's origin:

Autofill's originnamenumexpcvcaccount
https://merchant.example
https://psp.example
https://ads.example

Appendix: Terminology

An autofill is an operation that fills one or many form control elements in the fully active descendants of a top-level traversable with user attention. An autofill can only be initiated on a focused form control element.

An autofill fills a form control if it changes the form control‘s value. The value after the autofill is the *form control’s autofill value*.

A form control's autofill value is non-sensitive if it is a credit card type, a cardholder name, or a credit card expiration date.

A form control's origin is its node document‘s origin. An *autofill’s origin* is the focused form control's origin. The top-level origin is the top-level traversable's active document's origin.

shared-autofill is enabled in a document if the Is feature enabled in document for origin? algorithm on shared-autofill, the document, and the document's origin returns Enabled.

TODO: Update link to eligibility for autofill once the PR is closed.