Marketplace/Reviewers/Apps/Guide/WebExtensions
/!\ Do not edit /!\
cr is working on this offline.
Security Guide for Web Extension Reviewers
This is a guide for reviewers of Firefox OS Web Extensions (also known as "new-style add-ons") that focuses on the security aspects. Web Extensions have different security properties than apps, but before you start, please familiarize yourself with the general threat model for Firefox OS apps by reading our security guidelines for app developers and our security reviewer training.
Web Extensions are distributed and installed just like apps as ZIP archives. Superficially indistinguishable, it's easy to tell them apart once you look inside: If the archive contains a file called manifest.webapp, it's a web app. If it contains a file called manifest.json instead, it's a Web Extension. If it contains both, it's an app and the other manifest is ignored.
General considerations
In the scope of Firefox OS, Web Extensions are a modern variant of Firefox Extensions (also known as "old-style add-ons". Web Extensions are also supported in Google Chrome and Opera, and while in theory they should even be compatible, in practice they're usually not because they use browser-specific features or interact with browser-specific apps.
The main difference between Web Extensions and traditional Extensions is the manifest which is structured differently and uses different properties, but much to the same effect. In the near future, only Web Extensions will be supported in Firefox OS.
Web Extensions come in two major varieties: Content Scripts, and Background Pages. (Gecko is currently not supporting Event Pages, a non-persistent variant of Background Pages, but will be.) Content Scripts inject JavaScript files into web pages and apps, and background pages react to system events they register for. Web Extensions can also bundle both, but this document focuses on Content Scripts which are by far the most powerful and most common type.
Content Scripts
Content Scripts don't live on their own. They are injected into existing apps or web pages. The injection behavior is exclusively defined in the manifest. Here's an example of the manifest.json file of a password manager:
{
"manifest_version": 2,
"name": "Password Manager",
"description": "It is a password manager",
"version": "0.0.1",
"role": "addon",
"content_scripts": [{
"matches": "<all_urls>",
"js": ["js/ContentManager.js"]
},{
"matches": ["app://system.gaiamobile.org/index.html"],
"js": ["js/PasswordManager.js"]
}]
}
This manifest tells us:
- the Web Extension only contains content scripts, two of them
- "js/ContentManager.js" is injected into "<all_urls>"
- "js/PasswordManager.js" is injected into "app://system.gaiamobile.org/index.html", the system app.
Or in other words: Whenever the browser opens any web page (and that includes every app), js/ContentManager.js is executed, and whenever it loads the main page of the system app, js/PasswordManager.js is executed. Pretty much what you'd expect of a password manager.
Matches
For content scripts the main security concern with the manifest hence is the "matches" lines. Where scripts are injects determines the level of access and privileges it can obtain – and in the worst case abuse.
Matches follow the scheme://host/path format. Where scheme can be any of http, https, file, ftp, or app. ? can be used to match an arbitrary character, * matches anything. There is also one alias <all_urls> that is equivalent to * which in turn is equivalent to *://*/*.
If you're interested in the details, take a look at the source code of MatchPattern.jsm.
Execution Context
A content script does not run in the target context it is injected to, but in its private sandbox. Since its ‘this’ object is different from that on the target context, its window and document objects are also different. However, target context’s window and document objects can be accessed through a proxy object that is available in its scope.
A content script can
- access and modify all the target context’s objects and data.
- inject JS files into the target context through the target's DOM.
- access its Runtime API.
- access the Web Extensions API.
- can modify the target's web content through the webRequest API.
- indirectly make API calls with the permissions of the target context by injecting js.
- bypass the target context's CSP policy.
- register event listeners. [arbitrarily?]
- patch function calls in the target context and modify their behavior
A content script can not
- be accessed from JS code running in the target context.
- directly call APIs that require permission.
Threat model
Once you know where a Web Extension injects its content scripts, use the following table as a guide.
| Injection target | Threat | Recommendations |
|---|---|---|
| <all_urls>, * | Global data exfiltration, performance issues | Ensure injected script doesn't slow down the system, escalate to experienced sec reviewer |
| System App | Full device compromise | Escalate to experienced sec reviewer |
| SMS app | SMS content exfiltration, sending costly premium SMS | ... |
| Contacts app | Contact data exfiltration, redirection of calls and messages | ... |
| Specific privileged apps | Abuse of app permissions | |
| Specific certified apps | Abuse of app permissions | Escalate to experienced security reviewer |
| All web pages | ... | ... |
| Specific web pages | ... | ... |