-
Notifications
You must be signed in to change notification settings - Fork 32
API Proposal Protocol
- Irakli Gozalishvili (@gozala / gozala@mozilla.com)
- Dietrich Ayala (dietrich / dietrich@mozilla.com)
If you would like to provide feedback please use following link, you'll be able to select text fragments and post comments for them.
Over tha past few years new p2p protocols (IPFS, Dat, SSB) have emerged that are becoming increasingly more popular. Unfortunately rather then enriching web ecosystem and growing Firefox user base they are forced to being developed & grow user base outside usually via Electron based applications like Beaker Browser, Patchwork SSB client and alike. They also have correpsponding web-extensions (IPFS Companion, DatFox, PatchFox) but they are only able to redirect calls to either gateway & compromise on providing decentralization / p2p-ness (whic is the whole point) or redirect to a separately installed local server application and compromise on UX. Both option still suffer from:
- Lack of origin sepration, so all the content for corresponding protocol shares origin that poses security risks.
- Unusable URLs (Differ across machines. End up pointing to either localhost or gateway regardless of receiver's setup)
- Integration with rest of the web stack.
This naturally forces ecosystem to grow in Electron based solutions.
The Firefox has internal architecture with a plugable protocol support that delegates to a nsIProtocolHandler
implementation corresponding to a requested protocol (by URL scheme). The libdweb experimental protocol API uses this mechanism to allow add-ons implement custom protocol implemenattions (ipfs://
, dat://
, ssb://
) that allow proper origin separation. This document is a proposal for offering similar API for webextensions.
This section details a proposed webextensions API for extending firefox with custom protocol implementation. It is broken into a few high-level sections:
As with most existing webextension APIs, it requires static declaration in manifest.json
. Given that protocol_handlers
key already exists and mostly serves the similar purpose this proposal extends it's entries with set of optional keys:
-
uriHandlerScript
with value corresponding to a location of script bundled with an add-on that provides protocol implementation. -
uriIcon
with value corresponding to a location of a bundled icon for the protocol. -
uriIsTrustworthy
with a corresponding boolean value (defaults tofalse
) which if true claims secure context.
"protocol_handlers": [
{
"protocol": "ipfs",
"name": "IPFS peer-to-peer hypermedia protocol",
"uriTemplate": "https://ipfs.io/ipfs/%s"
"uriHandlerScript": "protocol/ipfs.js",
"uriIcon": "protocol/ipfs.svg",
"uriIsTrustworthy": true
}
]
If web-extensions declares protocol_handler
with both uriHandlerScript
and browser supports it should ignore uriTemplate
key, if browser that does not it will just ignore new keys and use uriTemplate
.
If uriHandlerScript
is used and uriIcon
is provided it is displayed on the left side of the corresponding URL in the address bar. When icon isn't provided icon used for corresponding web extension's moz-extension://
URLs should be used.
If uriIsTrustworthy
is set to true
content loaded from that protocol is presumed to be delivered securely and will subject to general secure context assement rules.
Note: While mentioned protocols (ipfs, dat, ipfs, ssb) have secure transport layer it would be practically impossible to assess if delivery was secure programatically, there for it's left to add-on reviewer to decide if claim is true.
It is also worse considering that WebExtensions can overcome all the restriction posed on non secure context so this does not provide additional attac vector to malicious web extension.
There a possibility that conflict may arise accross installed extensions providing implementation for the same protocol. Given that such conflicts can already arise for protocol_handlers
and proposal API isn't believed to make it more common no changes to to conflict resolution are proposed here.
Protocol scripts are loaded in unspecified background context (initial implementation will reuse background script code-base) which similar to Service Workers maybe activated or stopped nondeterministically there and number of protocol scripts may vary
In other words protocol handler has absolutely no guarantee about state outside of the handler.
Valid protocol handler script is require to define global handleRequest
funciton which will be invoked with an object implementing Request
compatible API for a corresponding URL and return object compatible with Response
API or a Promise
of such an object.
In practice
handleRequest
will be an async function that returnsResponse
compatible API.
The underlying mechanism will implement nsIProtocolHandler
for protocol schemes found in the manifest. And register them across parent & all child processes.
Currently Gecko requires
nsIProtocolHandler
to be registered both in parent & content processes. In the parent process implementation is used only for URL resolution while in child process it is used to assemblensIChannel
for the request URL.
Implementation will use standard URL resolution algorith and there call to newURI()
on corresponding nsIProtocolHandler
will complete at callsite without communication with corresponding protocol script.
Implementation will respond to a newChannel()
call on the corresponding nsIProtocolHandler
with an async channel, that on asyncOpen()
will asynchrnously trigger a call to a correspondig protocol script and pipe response back to opening nsIStreamListener
.
Proposed mechanism can do necessary IPC messaging to transfer request data from the child content proress to addon process that defines protocol and response data back from addon process the requesting content process.
Content origin will be determined according to the standard rules - defined by the scheme (protocol), host (domain), and port of the URL used to access it. Two objects have the same origin only when the scheme, host, and port all match.
Some operations are restricted to same-origin content, and this restriction can be lifted using CORS.
Even though underlaying nsIProtocolHandler
interface allows port support this proposal does not expose that capablity. URL resolution algorithm will strip out port from the URL.
URL resolution algoritms will recognize relative URLs like ./foo.js
, ../../icon.png
, /style.css
and resolve according to the standard rules used for https://
protocol resolution.
A context of the content will be considered potentially trustworthy (whic corresponds to URI_IS_POTENTIALLY_TRUSTWORTHY
protocol flag of nsIProtocolHandler
) if web extension claims that via uriIsTrustworthy
flag. Content from such protocol will be subject to general secure context assesment rules to determine it has secure context or not.
Protocols defined by web-extension will have regular content principal and no no access to any extended capabilities.
At the moment of writing content scripts only support a handful of hard-coded protocols. As a part of this proposal protocol support will need to be updated so that content scripts will be able to handle introduced protocols as well.
Extension defining custom protocol handler will need to perform an origin storage cleanup. It would be nice to have some UX that would allow user to preserve storage. It is out of the scope for this proposal though as it should fit into more general solution for preserving extension data.
- Malicious Addon
- Addon escalating privileges
- Addon deploynig phishing attac
- Other addon gaining additional privileges
- Malicious addon impersonating well known protocol
- Chrome UI spoofing
- Malicious Content (Served through addon)
- Malicious content exploiting addon for escalate privileges
- Malicious content impersonating well known content.
- Network Eavesdropper
- Active attack: MITM attack against cleartext network communication.
- Passive attack: Password sniffing or other private information gathering.
Distinct browser UI will be used to mitigate this attack
- Each protocol will have distinct URL schema similar to
moz-extension://
- Different icon (potentially provided by web-extension) will be displayed for the site info section (will display different icon from a lock that is used in
https
). - We could allow add-on supply custom icon (corresponding to a protocol), although there is a risk that add-on author might use icon similar to lock displayed for https. But there are still several options we could consider to mitigate that as well:
- Require review of supplied icon.
- Have set of icons that add-ons could choose from instead of providing one.
- Require SVG icon and ensure distiction from common icon via color.
Note: this does not address malicious addon from impersonating well known protocol (e.g ipfs). While this is a potential risk it in the same group as malicios addon requesting "Host Permissions" to alter https
content.
Protocol implementation will be loaded in a sandboxed addon process same as "backgrounds scripts" and there for will be subject to same restrictions as "background scripts". Only add-ons that declare permission corresponding to specific protocol schema will be able to accept requests for corresponding URLs and respond with plain data.
Other add-ons may be able to use custom protocol to consume what add-on implementing that protocol chose to expose through it. We are not going to restrict that since already existing APIs could be used to accompish same thing.
Each protocol will be assigned origin determined according to the standard rules - combination of the scheme (protocol), host (domain), and port of the URL used to access it. Two objects have the same origin only when the scheme, host, and port all match.
Content will be isolated in compliance to content origin policies and most operations will be restricted to same-origin, which could be lifted using CORS.
Additionally addon providing protocol implementation will be able to add extra layer of security via [Content Security Policy][] headers.
That would ensure that content is unable to gain additional privileges, except those that addon chose to expose (which addons can already do without this API).
There is a risk that protocol implementation could claim Secure Context without providing delivering content securely & potentially compromising secure connection. Since addons are already capable of doing it <unverified-claim>, but addons are already capable of it, which is why we'll leave it up to an addon author to uphold such claims.</unverified-claim>
This risk already exist with http
protocol which we mitigate by communicating it via browser UI and general advocacy of secure communications. We reuse same startegy of distinct browser UI and advocasy (through documentation, reviews, etc)