-
Notifications
You must be signed in to change notification settings - Fork 217
Browser extension provider communication #348
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
Open
jiexi
wants to merge
25
commits into
ChainAgnostic:main
Choose a base branch
from
jiexi:browser-extension-provider-communication
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
db1b0eb
Fork @gudahtt 's proposal
jiexi b96b182
WIP
jiexi 240ed2a
fleshing caip out more
jiexi c609592
Rationale. Add missing sections
jiexi 79f777c
Security and Privacy
jiexi 6641dd4
remove json-rpc providers from summary. update abstract
jiexi 6fad470
Update caip-browser_extension_provider_communication.md
jiexi c0e298c
Update caip-browser_extension_provider_communication.md
jiexi 6396b51
Update caip-browser_extension_provider_communication.md
jiexi 518c27e
update injecting code breakage text
jiexi e46a901
Merge remote-tracking branch 'origin/browser-extension-provider-commu…
jiexi 1cff079
Update caip-browser_extension_provider_communication.md
jiexi e7a8390
Update firefox caveat. Remove different extension id text
jiexi a2c083a
reword 'no safely make breaking changes' text
jiexi 4205dc5
use 'inpage injected providers' in summary and abstract
jiexi 5f093b1
Update simple summary and abstract
jiexi 1ac953f
Update caip-browser_extension_provider_communication.md
jiexi 0136d89
Update caip-browser_extension_provider_communication.md
jiexi fea1505
Remove message format todo
jiexi 54b6041
Merge remote-tracking branch 'origin/browser-extension-provider-commu…
jiexi 6d14374
update json schema
jiexi 649f856
add privacy fingerprint considerations
jiexi 392fa51
address comments
jiexi 368f770
replace contentscript with 'content scripts'
jiexi dfe38ae
security considerations
jiexi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| --- | ||
| # Every document starts with a front matter in YAML enclosed by triple dashes. | ||
| # See https://jekyllrb.com/docs/front-matter/ to learn more about this concept. | ||
| caip: <to be assigned> | ||
| title: Web extension provider communication | ||
| author: Mark Stacey (@Gudahtt), Jiexi Luan (@jiexi) | ||
| discussions-to: <URL> | ||
| status: Draft | ||
| type: Standard | ||
| created: 2022-11-28 | ||
| --- | ||
|
|
||
| <!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. The title should be 44 characters or less.--> | ||
|
|
||
| ## Simple Summary | ||
| <!--"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the CAIP.--> | ||
| This CAIP discusses the motivation, specification, and rationale for a proposal aimed at improving how web extension wallets interact with websites. It outlines the current method of injecting JavaScript provider APIs into websites, its advantages, and its numerous disadvantages, such as security concerns, performance issues, and the risk of breaking websites. An alternative strategy is proposed that specifies a standard communication specification over a new transport layer which enables websites to be able to embed their own provider as a library, addressing the disadvantages of injecting providers into websites and improving web extension interoperability as a whole. | ||
|
|
||
| ## Abstract | ||
| <!--A short (~200 word) description of the technical issue being addressed.--> | ||
| In the current web extension wallet ecosystem, most wallets communicate with websites by injecting a JavaScript provider API (`window.ethereum`) directly into webpages as a global variable. This method offers simplicity for web developers and ensures compatibility across extensions but raises significant concerns regarding security, performance, and potential disruption of website functionality due to the need for extensive permissions for the injection of additional code that have the potential to cause webpage breakage. An alternative approach involves websites embedding their own provider libraries, which could mitigate these issues by reducing required permissions, enhancing performance, and providing developers with greater control over provider integration. | ||
|
|
||
| This proposal addresses the challenge of maintaining interoperability between web extensions and websites by standardizing an extensible communication protocol through the `externally_connectable` interface. Using the `externally_connectable` interface is less intrusive and more performant than the current pattern of injecting an inpage provider as a global variable. | ||
|
|
||
| This proposal is not yet applicable to Firefox due to lack of support for `externally_connectable`, but they are considering implementing it. | ||
|
|
||
| ## Motivation | ||
| <!--The motivation is critical for CAIP. It should clearly explain why the state of the art is inadequate to address the problem that the CAIP solves. CAIP submissions without sufficient motivation may be rejected outright.--> | ||
| Web extension wallets today will typically inject a JavaScript provider API into websites as a global variable. For example, in the Ethereum ecosystem this provider API is standardized in EIP-1193, and is conventionally injected as `window.ethereum`. | ||
|
|
||
| This injected API strategy has some advantages: | ||
| * For websites developers, using a global variable is simple and requires no effort on their part to setup. | ||
| * It allows websites to support any web extension following this standard with no additional effort. | ||
|
|
||
| However, the injected API strategy has many disadvantages: | ||
| * It depends upon the web extension having read and write access to every website the user visits, which is a scary permission that web extension authors might otherwise be able to avoid asking for. | ||
| * It slows down every website by injecting additional code to be parsed and executed. It even slows down the initial page load in most cases, because many web extensions inject the provider synchronously to maintain compatibility with websites that expect it to be available immediately. | ||
| * In some cases, injecting code into a webpage may break its original intended behaviors. | ||
| * It provides no way for web extension authors to safely make breaking changes to their provider API without having to also inject extra code for the purposes of maintaining backwards compability for websites that may still rely on those legacy APIs. | ||
|
|
||
| An alternative strategy would be for a website to embed its own provider. A provider could be offered as a library, to be embedded by the website author. This strategy can address all disadvantages of the injected provider approach: | ||
| * If this strategy became widespread enough, it would allow some web extensions to stop asking for write access to all pages. | ||
| * NOTE: Should mention discovery somewhere since that will require injection still | ||
| * The website author can control when the provider is initialized, and fine-tune performance. | ||
| * No code needs to be injected, so websites would no longer be broken by injected code. | ||
| * The provider library can be published with breaking changes, allowing changes to the API without needing to embed legacy code in each website. | ||
|
|
||
| A provider library can be similarly easy to use for website authors as well, requiring nothing more than a single script tag to import a library and get an equivalent experience to using an the injected provider. | ||
|
|
||
| Web extension inter-operability is a challenge for embedded providers though. That is what this proposal means to address. Today there is no way to write a provider such that it is compatible with any web extension. Web extensions differ today in how they communicate with wallets, from the messaging system used to the messaging format. These details often aren't publicly documented or treated as a public-facing API, so they can change without notice, making it risky even to embed support for popular conventions used today. | ||
|
|
||
| A standard method for providers to communicate with web extensions would allow website authors to embed their own providers without losing web extension inter-operability. | ||
|
|
||
| ## Specification | ||
| <!--The technical specification should describe the standard in detail. The specification should be detailed enough to allow competing, interoperable implementations. --> | ||
|
|
||
| ### Language | ||
|
|
||
| The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", | ||
| "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" written in | ||
| uppercase in this document are to be interpreted as described in [RFC | ||
| 2119](https://www.ietf.org/rfc/rfc2119.txt) | ||
|
|
||
| ### Summary | ||
|
|
||
| Web extensions should expose a standard interface over [`externally_connectable`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/externally_connectable) to enable the inter-operability of embedded providers. | ||
|
|
||
| ### Message format | ||
|
|
||
| ```json | ||
| { | ||
| "$schema": "https://json-schema.org/draft/2020-12/schema", | ||
| "$id": "/caip-x/schemas/provider-request.schema.json", | ||
| "title": "Provider / Web Extension message", | ||
| "description": "A request sent between a provider and a web extension.", | ||
| "type": "object", | ||
| "properties": { | ||
| "type": { | ||
| "description": "The message type, used to identify this as a CAIP-X message", | ||
| "const": "caip-x" | ||
| }, | ||
| "data": { | ||
| "description": "A CAIP-25/27/285/312/319 JSON-RPC message", | ||
| "type": "object" | ||
| } | ||
| }, | ||
| "required": ["type", "data"] | ||
| } | ||
| ``` | ||
|
|
||
| ### `externally_connectable` | ||
|
|
||
| A web extension can use the `externally_connectable` manifest field to accept messages from websites and other extensions. This permission can be configured to limit which sites and other extensions can send messages to the web extension. How this permission is configured is out-of-scope for this proposal; this proposal only concerns sites that the web extension allows messages from. | ||
|
|
||
|
|
||
| The web extension can: | ||
| * handle a connection from the website or other extensions by using `chrome.runtime.onConnectExternal.addListener((port) => {...})` | ||
| * send messages by using `port.postMessage()` | ||
| * receive messages by using `port.onMessage.addListener()` | ||
| * incoming messages should be validated according to the message format specification above | ||
|
|
||
| The webpage embedded provider can: | ||
| * initiate a connection with the web extension by using `port = browser.runtime.connect()` | ||
| * send messages by using `port.postMessage()` | ||
| * receive messages by using `port.onMessage.addListener()` | ||
|
|
||
| ### Caveats | ||
| Currently Firefox does not support `externally_connectable` yet, but they are [considering implementing it](https://bugzilla.mozilla.org/show_bug.cgi?id=1319168). Meanwhile, extension wallets on Firefox will need to continue injecting an inpage provider for the website. | ||
|
|
||
| ## Rationale | ||
| <!--The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.--> | ||
| The current reliance of extension wallets on content scripts is highly unideal as it is overly permissive in regards to what the wallet is ultimately trying to achieve which is to provide an entrypoint for a website to the wallet. This paradigm exists because of website reliance on inpage injected providers. | ||
|
|
||
| A better pattern would be for dapps to be able to connect directly to the wallet without the wallet needing to inject and run code on the webpage at all. This can be achieved by using the the `externally_connectable` transport layer, which allows website to communicate with wallets without requiring code injection. This reduces permissions required by extensions and improves website performance. Additionally, this simplifies the complicated situtation website maintainers may find themselves in when it comes to building and designing around code being forceably injected into their pages. Not to mention the headache around debugging, monitoring, and triaging bug reports that may not have originated from their application logic but is being caught by monitoring tools. | ||
|
|
||
| Unfortunately, using `externally_connectable` by itself will not be sufficient as dapps will still need to know how to actually communicate with the wallet, but if each wallet has a differently shaped API then this approach cannot scale. Because of that, this CAIP also proposes an extensible message format to use in conjunction with `externally_connectable`. Using a standardized message format allows websites and wallets to be inter-operable in the same way they are today with EIP-1193. It is backwards compatible as it allows the website and extension to disambiguate the newly proposed messages from any existing messages that may already be sent on this interface. Finally, it is forwards compatible it also enables extensibility for different formats in the future. | ||
|
|
||
| Web extension inter-operability is the key to enabling generalized provider implementations. Generalized provider implementations allows for convenient adoption by websites, leading to more wide spread adoption of the standard as a result. | ||
|
|
||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. reminder: maybe mention other uses of the transport being possible? |
||
| ## Test Cases | ||
| <!--Please add test cases here if applicable.--> | ||
|
|
||
| ## Security Considerations | ||
| <!--Please add an explicit list of intra-actor assumptions and known risk factors if applicable. Any normative definition of an interface requires these to be implementable; assumptions and risks should be at both individual interaction/use-case scale and systemically, should the interface specified gain ecosystem-namespace adoption. --> | ||
| Inclusion of `externally_connectable` does not require the user to also give the wallet extension permission to use `content_scripts`. Content scripts are a higher-privileged permission with ability to run scripts on any webpage. `externally_connectable` simple enables a way for webpages to directly communicate with extensions. | ||
|
|
||
| ## Privacy Considerations | ||
| <!--Please add an explicit list of intra-actor assumptions and known risk factors if applicable. Any normative definition of an interface requires these to be implementable; assumptions and risks should be at both individual interaction/use-case scale and systemically, should the interface specified gain ecosystem-namespace adoption. --> | ||
| Exposing the wallet API over `externally_connectable` opens a migration path towards a bring-your-own provider model in which web extensions can reduce their fingerprint by no longer having to inject their own provider into every webpage. | ||
|
|
||
| It should be noted however that this API is still fingerprintable based on the return values from a CAIP-25 request. A malicious actor could make several CAIP-25 requests with a single scope and/or account ID to determine what scopes and/or accounts the wallet supports based on whether that request returns immediately with an unsupported error or not. This can be mostly mitigated by rate liming and disallowing concurrent CAIP-25 requests from the same origin. It is no worse than the current status quo with EVM methods. | ||
|
|
||
| ## Backwards Compatibility | ||
| <!--All CAIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The CAIP must explain how the author proposes to deal with these incompatibilities. CAIP submissions without a sufficient backwards compatibility treatise may be rejected outright.--> | ||
| `externally_connectable` does not conflict with `content_scripts` which currently enable injected providers. This CAIP does not require changes to an extension wallet's existing injected providers pattern. | ||
|
|
||
| The message format used by this CAIP allows extensions that already use `externally_connectable` to serve requests to continue doing so. This is because the new message format introduced by this CAIP is easily identifiable and can be easily ignored/filtered by any pre-existing handlers. Additionally, the message format is also flexible enough to be compatible with future APIs that may also share the same `externally_connectable` entrypoint. | ||
|
|
||
| ## Links | ||
| <!--Links to external resources that help understanding the CAIP better. This can e.g. be links to existing implementations.--> | ||
| * [externally_connectable](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/externally_connectable) | ||
| * [Mozilla bug report: "Implement externally_connectable from a website"](https://bugzilla.mozilla.org/show_bug.cgi?id=1319168) | ||
|
|
||
| ## Copyright | ||
| Copyright and related rights waived via [CC0](../LICENSE). | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.