# Autofill across iframes Chrome Autofill fills in frame-transcending forms like the following pseudo-code example. ```
Cardholder name: Credit card number: Expiration date: CVC:
``` 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](#appendix-terminology). 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: ``. 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 origin | `name` | `num` | `exp` | `cvc` | `account` | |----------------------------|:--------:|:--------:|:--------:|:--------:|:---------:| | `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](https://github.com/whatwg/html/pull/8801) is closed. [FormForest::GetRendererFormsOfBrowserForm()]: https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/content/browser/form_forest.cc;l=618-623;drc=94fbbc584c5d42f0097a9cb28b355853d2b34658 [active document]: https://html.spec.whatwg.org/#nav-document [eligibility for autofill]: https://schwering.github.io/html/#eligible-for-autofill [Is feature enabled in document for origin?]: https://w3c.github.io/webappsec-permissions-policy/#algo-is-feature-enabled [focused]: https://html.spec.whatwg.org/#focused [fully active descendants of a top-level traversable with user attention]: https://html.spec.whatwg.org/#fully-active-descendant-of-a-top-level-traversable-with-user-attention [same origin]: https://html.spec.whatwg.org/multipage/browsers.html#same-origin [node document]: https://dom.spec.whatwg.org/#concept-node-document [origin]: https://dom.spec.whatwg.org/#concept-document-origin [PCI-DSS best practices]: https://www.pcisecuritystandards.org/ [shared-autofill]: https://schwering.github.io/shared-autofill/ [top-level traversable]: https://html.spec.whatwg.org/#top-level-traversable [value]: https://html.spec.whatwg.org/#concept-fe-value