Firefox/Features/Web Payments/Privacy & Security Considerations
- 1 Introduction
- 2 How It Works
- 3 Local Storage of User Information ("Data At Rest")
- 4 Interaction with Merchant Website ("Data in Motion")
- 5 Information Leakage
- 6 Device Fingerprinting
- 7 Private Browsing Mode
- 8 Data Validation
- 9 User Interaction
- 10 Process Separation and Sandboxing
- 11 Open Issues
- 12 Privacy and Security Roadmap
The web payments feature enables a faster, more secure payment process for online commerce. This page describes the privacy and security characteristics of the initial release in Firefox, as well as a roadmap of future enhancements.
How It Works
Traditionally, the checkout process for an e-commerce website has been loaded in web content. As a result, the shopper has filled out payment-related details (credit card number, card expiration date, card security code, billing address, shipping address, etc.) at the merchant site, often in a workflow spread over several web pages. When the user has provided all required information and is satisfied with the final order details, the shopper clicks a button like "Place Order" and the shopper's payment instrument (e.g., a debit card) is authorized to pay the amount due. Although form autofill can make the checkout process somewhat less inconvenient, the user experience varies from merchant to merchant and can contain various security vulnerabilities.
By using the Payment Request API (based on the W3C Payment Request and the W3C Basic Card Payment specifications), the web payments feature will present a standardized, more secure checkout flow in a trusted browser dialog window. At a high level, the workflow is as follows:
- At the merchant website, the user chooses items to purchase and clicks a "Pay" button of some kind.
- The merchant website invokes the PaymentRequest.show() method in the browser.
- Firefox presents a browser dialog window to complete the purchase.
- In the browser dialog window, the user provides information requested by the merchant (credit card number, shipping address, etc.), optionally directing Firefox to save the information locally for re-use in future transactions.
- When the user completes the in-browser workflow, the browser sends a PaymentResponse to the merchant website with the requested information.
- Optionally the merchant website might ask the user to correct an error (e.g., an invalid postal code) and would then call the PaymentRequest.retry() method; the user would then correct the error and finish the workflow.
- When the merchant website accepts the PaymentResponse, it calls the PaymentRequest.complete() method and Firefox closes the browser dialog window.
Local Storage of User Information ("Data At Rest")
If the user opts in to storage of user data (e.g., credit card numbers and shipping addresses) for convenience in future payment flows, Firefox stores that data on behalf of the user.
This data is not stored "in the cloud" but only on the user's own device (e.g., on the user's laptop computer). However, if a user has enabled the Sync feature, then data might be synchronized across devices (strictly speaking, Sync is not a way to store user data but a way to securely share data among multiple devices).
Depending on what the user enters and asks to be retained for future use, Firefox will store the following data locally:
- credit card number
- credit card expiration date
- billing address
- shipping address
Note: Firefox never stores the credit card security code (CVV/CCV). If requested by a merchant, the user always needs to provide this information in order to complete a payment.
How Data is Secured on Device
For release in Firefox Nightly (planned in Q3 2018), user data is stored as it currently is in form autofill (see this profiles page) for more details). In parallel with development of the web payments feature, the Firefox team is building a new secure storage method that will use native operating system services to generate a device-specific key and then encrypt data at rest using that key (see Bug 1463865); in the initial release this method will be used to protect credit card information, and in future releases might be used to protect other kinds of data as well.
Interaction with Merchant Website ("Data in Motion")
The payment request from merchant to browser and the payment response from browser to merchant are always protected by Transport Layer Security (HTTPS) because the Payment Request API can be used only in secure contexts.
When the payment process is loaded in web content on a merchant website, it is easy for code running on that site (often third-party code that has not been vetted for privacy and security vulnerabilities) to engage in wholesale data exfiltration (e.g., via form tracking and session replay scripts), to track the user's mouse movements, to trick the user into clicking malicious but ephemeral links (see this post for related attacks), etc.
By contrast, when the payment process is handled by trusted, standardized code in a browser dialog window, the user's form input (credit card number, shipping address, etc.) is protected against many of these attacks.
In addition, we have instituted several policies to ensure that user data is not leaked to the merchant site:
- Firefox does not share the user's full shipping address until the user approves the payment at the very end of the in-browser workflow (see Bug 1443735). Before then, Firefox shares only the minimum information (country and postal code) needed to determine shipping viability and cost.
- Although a merchant website could try to gather the user's country and postal code by calling the PaymentRequest.show() and .abort() functions in quick succession (even without the user noticing), to prevent abuse we have implemented a minimum amount of time (5 seconds) to display the payment dialog window, thus making it difficult for a website to trick a user into sharing this information (see Bug 1447773).
During an early privacy review of the Payment Request API, Lukasz Olejnik raised concerns about the ability of website scripts to "fingerprint" a user by repeatedly using the .canMakePayment() call to determine which payment methods and payment instruments the user has installed. To mitigate this risk, Firefox allows the .canMakePayment() call only in top-level browsing contexts and only after the user "gestures" to allow .show() from the website. Furthermore, Firefox matches only on installed payment handlers or supported payment methods (e.g., basic-card), not on card networks (e.g., Visa or Amex).
Because fingerprinting attacks are extremely creative (see the EFF report How Unique Is Your Web Browser?), it is possible that additional attack vectors might be enabled by the W3C Payment Request API, perhaps in combination with non-payment vectors; we are investigating this possibility.
Private Browsing Mode
Private browsing mode is a method whereby Firefox prevents session data from being written to local storage and protects the session data from online tracking. Because this is an important privacy feature, Firefox takes several steps to prevent a website from using the Payment Request API to discover whether private browsing mode is in force. In addition, several other protections are in place:
- By default, Firefox does not save to local storage any information that the user enters (e.g., credit card data or shipping address when editing payment details). However, the user can override this default by clicking a checkbox in the appropriate screens.
- Firefox does not automatically present in the user interface the last credit card and shipping address used at this website, even if that information is known to Firefox.
- Firefox does not update storage metadata (e.g., the last-modified or last-used time for credit card data or shipping addresses).
As part of the W3C Payment Request API, the merchant website can provide certain untrusted strings to the browser; these include:
- PaymentItem labels (e.g., products in a shopping cart)
- The web origin of the merchant website (which could include mixed scripts, bidirectional domain labels, confusable characters, etc.)
- Error strings, especially the generic error message
Firefox should validate and sanitize all untrusted strings, for instance by limiting their display length (e.g., truncate to 64 bytes or fewer, as is done for relying party names in the Web Authentication API), always using UI elements to provide a clear boundary around these strings, not allowing these UI elements to overflow into other elements, etc.
User must provide explicit consent granting card data:
- UX design should include explicit confirmation from the user (such as CVV confirmation before the pay button is enabled).
- We should prevent attacks where the user is tricked into interacting with the Payment Request dialog (e.g. clickjacking, UI redress attacks)
It must be clear to the user which page initiated the payment:
- Navigation away from a page showing a Payment Request dialog either should be prevented or the dialog should abort.
- If we plan to show origin information in Payment dialog (as per current UX spec, but not implemented yet) this needs to avoid all URL spoofing/truncation attacks.
Web pages must not be able to interfere with the Payment Request dialog:
- Prevent overlaying content on top of the dialog, or forcing part of the dialog off screen
- Ensure that any string originating from content are sanitized for display
Prevent web pages from coercing the user into payment:
- An abusive website could repeatedly invoke the payment request dialog and thus hold the user hostage until they pay. To prevent this, the proposed design will allow the user to close the whole tab while the Payment Request dialog is open.
Process Separation and Sandboxing
To help mitigate against sandbox violations, cross-site scripting attacks, and Spectre-related vulnerabilities, care has been taken to implement the Payment Request dialog in a separate process from the process that handles sensitive user information such as credit card numbers (see Bug 1460425), thus helping to prevent a compromised web content process from reading this data.
- What happens if the dialog appears during DOM or UI fullscreen?
- What happens if the dialog appears in different variants of popup windows (e.g. consider window.open features)?
- It would be helpful to include diagrams of the UI workflow and protocol state machines.
- It would be helpful to describe the process model or point to documentation on another page.
- We need to add a more detailed discussion of fingerprinting attacks.
Privacy and Security Roadmap
Future features will likely include:
- Support for tokenized credit card data (e.g., via the W3C Tokenized Card Payment Method) so that credit card information is not sent from the browser to the merchant; instead, the browser sends a payment authorization token.
- Support for stronger encryption of payment requests and responses using a standardized approach such as the emerging W3C Payment Method Encryption proposal.
- Reliance on underlying adjustments in Firefox to address issues such as timing-related side channel attacks (e.g., using process-per-origin separation as in Project Fission).