Efficient method to script embedded pages in an addon

Continuing the discussion from How to open an addon page in Firefox?:

We sometimes need to script an SDK-based add-on page with features similar to XUL-based pages or chrome:// HTML pages.
When we use sdk/tabs to script pages if the user opens an add-on page directly (e.g. using bookmarks) the UI is dead.
Using sdk/page-mod with pattern resource://<id>/* can script an add-on’s pages with ability to communicate with privileged code in a more consistent way, but is this efficient? Will this unnecessarily make Web slightly slower? It it more likely to produce security holes?

What is the best way to do this? Add-on pages should have the needed privileges without writing the same code as Web contents.

1 Like

Add-on pages like chrome:// do have the same privelages, but as we are moving to e10s its advisable that you only do message communication from this page. It’s much friendlier on the memory, and no need to import these expensive XPCOM and other components.

Using a resource:// page should work fine, you can add an array of paths to your scripts to get included. Here is an addon that uses the SDK and does this:

https://addons.mozilla.org/en-US/firefox/addon/justintv-stream-notificatio/?src=userprofile

Resource URIs are mostly unprivileged and that is good for security. However:
resource:// is pretty much accessible from Web. And by default all files in SDK-based add-ons are in resource://

Does anyone know how to prevent embedding resource://addon-name-here/icon.png from Web content for example?

The problem. Detect an add-on from unpriv. Web content:

<img onload="..." onerror="..." src="resource://addon-name-here/icon.png" />

Also:

<script>
// This code suppresses most errors from CommonJS code
var require = function () {
return new Proxy(function () {}, {get(t, n, r){return r}});
};
var exports = {}, module = require;
</script>
<!-- The following script will run without the privileges. So no trivial security issues but terrible for privacy. -->
<script src="resource://addon-name-here/some/script.js" onerror="..." onload="..."></script>

This is very bad for privacy of our users.

Some may argue that add-ons anyway change browser fingerprints so resource:// is not a problem. However, some add-ons can be written in a such way that fingerprinting is otherwise nearly impossible. resource:// being detectable from Web is the remaining privacy threat, which allows for classifying users based on installed add-ons.

Some add-ons do require their resource:// files being available from Web. However, that is no excuse for this leak available for every add-on. Most add-ons don’t need this “feature”.

Is there any plans in Mozilla to restrict resource:// URIs? This is rather critical. Some downstream developers of Firefox are interested in it.

1 Like

The contentaccessible flag determines if a chrome package is accessible by content or not. resource packages have this on by default. I’m not sure if you can just set contentaccessible=no for resource packages, but you should give it a try.

What is the right way to control flags on resource registrations made automatically for SDK-based add-ons then?

Thank you in advance.

This issue is best resolved with a new flag in package.json. (In my opinion, contentaccessible should default to no for resource URIs.)

Proposed steps:

  1. Deprecate the use of contentaccessible resource URIs in the core Firefox. Add-ons are not affected. (just print a warning) Also, add a option to set
    contentaccessible=no in package.json. resource URIs (or equivalents) should be web-inaccessible by default for WebExtensions.
  2. Make contentaccessible=no the default for add-ons. Notify the developers of the add-ons that rely on availability of resource URIs from the Web. contentaccessible=yes will be an opt-in for resource URIs.

More on the core Firefox (a bit off topic here):

  • Firefox now reports 45.0 in UA strings for the real version 45.0.1. (And the same 45.0 for 45.1.1esr etc.) This is a good Firefox thing for privacy/security compared to Chromium/Chrome.
  • However, precise scanning of resource URIs often reveals the real versions to Web contents.
  • Privacy add-ons can spoof OS or other information to Web. However, resource URIs from the core of Firefox reveals everything. Moreover, such add-ons (and precise versions) are easily detected by scripts on a Web page.

Result:

Unrecognized chrome manifest modifier 'contentaccessible=no'.

The SDK is in maintenance mode as WebExtensions are rolled out, so I think that getting this change in is going to be a big challenge. If you need this particular feature, you’ll either need to use WebExtensions or create a non-SDK add-on.

Can you please make resource: URIs (and anything related) barred from Web for WebExtensions then? That sounds best suited for WebExtensions. Chromium based browsers don’t have resource: URIs (but equivalents) anyway. If it is impossible, make that permission explicit opt-in in manifest.json. This is certainly good for privacy, and for Firefox.

Edit

If all WebExtensions use is the new moz-extension: scheme, and it is not Web-accessible at all, this can be solved in the future (years later).

  • Does the WebExtensions API make use of any scheme other than moz-extension:?
  • Does leaving web_accessible_resources make every moz-extension: resource related to the add-on completely inaccessible and undetectable from Web?

Implementing nsIContentPolicy did not enable filtering against most resource: URIs. Is this intended? If so, what to use for intercepting them?

As far as I know, WebExtensions can’t and won’t use resource: URIs, and only things that are explicitly declared as web accessible will leak into content.

I don’t know the answer to the nsIContentPolicy question.

Where can I get help for such deep topics?

Until resource: URIs become web-inaccessible we can work around by:

  1. Blocking some or all access attempts to them from content, or
  2. Using chrome: resources with somehow reduced privileges instead of resource: ones (Is that possible for scripts and (X)HTML files? There is remoterequired flag, though)

EDIT

  • At an add-on level, we could randomize part of the resource: URI registration for each installation to defend against scanning, just like the moz-extension: scheme:
    resource://addon-name-<random>/...
    • This is possible by manual unmounting and re-mounting. All absolute references must be corrected accordingly when we do this.

There are various specialized channels on IRC where you can try asking. The Firefox developers channel might have the answer.