Skip to content

API Proposal Protocol

Irakli Gozalishvili edited this page Oct 17, 2018 · 4 revisions

Webextensions protocol API proposal

Feedback

If you would like to provide feedback please use following link, you'll be able to select text fragments and post comments for them.

Background

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.

Proposal

This section details a proposed webextensions API for extending firefox with custom protocol implementation. It is broken into a few high-level sections:

Permissions

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 to false) 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.

Web extension conflicts

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 Handler Script

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 returns Response 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 assemble nsIChannel 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.

Protocol properties

Content origin

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.

Port support

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.

Relative URL Support

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.

Content Principal

Protocols defined by web-extension will have regular content principal and no no access to any extended capabilities.

Content Scripts

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.

Origin Storage

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.

Threat model

Possible threats

  • 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.

Threat mitigation strategies

Prevent chrome UI spoofing / impersonation

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.

Preventing add-ons from escalating privileges

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.

Prevent content from escalating privileges

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>

Prevent Network Eavesdropper

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)