• Skip to main content
  • Select language
  • Skip to search
MDN Web Docs
  • Technologies
    • HTML
    • CSS
    • JavaScript
    • Graphics
    • HTTP
    • APIs / DOM
    • WebExtensions
    • MathML
  • References & Guides
    • Learn web development
    • Tutorials
    • References
    • Developer Guides
    • Accessibility
    • Game development
    • ...more docs
Add-ons
  1. MDN
  2. Mozilla
  3. Add-ons
  4. Security best practices in extensions

Security best practices in extensions

In This Article
  1. Web content handling
  2. The sidebar: a use case
  3. Using eval() in an extension
  4. Sandboxed HTTP connections
  5. Handling of logins and passwords
  6. APIs and other data handling
  7. Remote JavaScript and Content
  8. evalInSandbox
  9. Third-party JavaScript
  10. Conclusion

Add-ons using the techniques described in this document are considered a legacy technology in Firefox. Don't use these techniques to develop new add-ons. Use WebExtensions instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.

From Firefox 53 onwards, no new legacy add-ons will be accepted on addons.mozilla.org (AMO).

From Firefox 57 onwards, WebExtensions will be the only supported extension type, and Firefox will not load other types.

Even before Firefox 57, changes coming up in the Firefox platform will break many legacy extensions. These changes include multiprocess Firefox (e10s), sandboxing, and multiple content processes. Legacy extensions that are affected by these changes should migrate to WebExtensions if they can. See the "Compatibility Milestones" document for more.

A wiki page containing resources, migration paths, office hours, and more, is available to help developers transition to the new technologies.

Draft
This page is not complete.

This document is intended as a guide for developers to promote best practices in securing your extension. Your goal is to keep your users safe. Some items mentioned are strict guidelines, meaning that if you don't follow them then your add-on will not be approved on Mozilla add-ons. Other items are recommendations. The difference will be clearly flagged.

This is written from the perspective of a Firefox extension, but most items apply to extensions for other Mozilla-based applications such as Thunderbird or SeaMonkey.

Web content handling

In general the best way to ensure that the browser is not compromised when you load content is to make sure it does not have those privileges. A more detailed explanation of this process is in Displaying web content in an extension without security issues.

The privileges that a document gets also depend on where it comes from. For example, if you load a chrome URL, this means the content has been registered with Firefox and has full access. Content from a domain (such as http://www.example.com) can only access that same domain. Files
loaded using the file protocol can access files on the user's disk and other local devices. There are ways to get around the content/chrome security barrier, if for example, you want a web page to send a notification to the add-on (or vice versa). One way to do this is to use custom DOM events; see Interaction between privileged and non-privileged pages.

Regardless of where the document comes from, you can further restrict what it can do by applying properties to the document holder, known as the docshell.

frame.docShell.allowImages = false;
frame.docShell.allowJavascript = false;
frame.docShell.allowPlugins = false;

There are more examples listed in the document listed above in this section. In certain circumstances you may want to run code in your extension, but you would like to give it restricted privileges. One of the best ways to do this is to use Components.utils.evalInSandbox(). Note that objects passed into the sandbox are restricted, but objects that come back out from it are not. Refer to the document to find out how to avoid such pitfalls. For more information, refer to the evalInSandbox section.

The sidebar: a use case

The sidebar in Firefox is designed to hold both chrome (privileged) content and Web (nonprivileged) content, the latter being in the form of Web pages. These Web pages can come from a server, or come from local HTML files bundled with the extension. For pages coming from the server, you need to take steps to ensure that the content can not call back into the Web browser and run malicious code. The main way to do this is by creating an iframe or browser element in the sidebar, and loading your content there. Give the element a type="content" attribute, which essentially sandboxes the code there and blocks callback rights into chrome.

Using eval() in an extension

Using the built-in JavaScript eval function is frowned upon in the context of extensions. While there are some legitimate use-cases, most of the time there are safer alternatives. This blog post offers some excellent reasons not to use eval().

Sandboxed HTTP connections

The main purpose of sandboxed HTTP connections is to interact with a web service, without interfering with the cookies set in the browser by that service/site. For example, if you are loading pictures or other data from a photo sharing site, you can sandbox your connections to that site so that the normal browsing of that site by the user in the main Firefox browser is not affected. For a real world use case, take a look at this blog post.

Handling of logins and passwords

There are various ways of storing data in Firefox, but for user logins and passwords, you should use the Login Manager. This is the same store that holds the logins from web pages, and passwords can only be retrieved using a site/username pairing known to the author. The convention for extensions is to use a chrome url for the site identifier, to avoid clashes with logins for sites. It could be the case that your extension provides a different tool or tools for services on your site.

This approach is preferable because it provides users with a familiar interface for interacting with logins, via the Firefox Password Manager. When users clear logins using the "Clear Recent History" option, it will include your extension's data.

APIs and other data handling

Web content is more than just pages, and more and more add-ons are interacting with web services via an Application Programming Interface (API). Many of the items talked about so far in this document apply in this sphere, but here are some additional tips:

  • API providers should use the https protocol, which provides better protection for data passed over the network.
  • JSON has become a popular data format for return formats for Web services. Be sure to read Using native JSON to find out the correct way to handle it.
  • APIs can't be used with self-signed certificates.

Remote JavaScript and Content

There are a number of ways of remote scripts being used in extensions. They can be included in content, or downloaded at intervals.

Non-chrome urls in chrome XUL or HTML such as the following example are not allowed:

<script type="text/javascript" src="http://mysite.greatsite.com/js/wow-content.js" />

In general, scripts that are from remote sources that run in the chrome context are not acceptable, as many times the source of the script can never be 100% guaranteed, and they are vulnerable to man-in-the-middle attacks. The only legitimate environment for remote scripts is to run in a sandbox. For more information, refer to the evalInSandbox() section.

evalInSandbox

The evalInSandbox document explains very well how it works, so there will be no repetition here. The usefulness of it and power of how it works is best illustrated by the popular Greasemonkey extension, which works on the premise of scripts being downloaded and stored locally, to be injected into the web content context via the sandbox. Many extensions use the Greasemonkey compiler to bundle it in their extension for convenience. If you choose to do so, beware when making edits to the bundled files so as not to break the well thought out security architecture.

Third-party JavaScript

In the context of Web sites, using JavaScript written by others is very common. It is not unheard of in add-ons as well, and can provide a useful way to avoid code duplication and accelerate development. This article is about websites, but gives some insights into the general risks. When you do include other scripts, there are a number of things you can do to ensure their integrity and safety for users. The first is to always get it from a trusted source. Another thing you should do is namespace it just in case other add-ons include it. For example, if you're using jQuery, there's jQuery.noConflict().

Conclusion

Security can't be taken for granted, and for every release of your add-on, a new security audit should take place. A good place to keep up with Mozilla security announcements and security discussion is at the Mozilla Security Blog.

Document Tags and Contributors

Tags: 
  • Add-ons
  • Best practices
  • Extensions
  • Guide
  • Security
 Contributors to this page: bunnybooboo, wbamberg, kmaglione, MickeyMouse420, kscarfone, lahabana, Brettz9, Sheppy, Kinger
 Last updated by: bunnybooboo, Apr 20, 2017, 5:06:47 PM
See also
  1. WebExtensions
  2. Getting started
    1. What are WebExtensions?
    2. Your first WebExtension
    3. Your second WebExtension
    4. Anatomy of a WebExtension
    5. Example WebExtensions
  3. How to
    1. Intercept HTTP requests
    2. Modify a web page
    3. Add a button to the toolbar
    4. Implement a settings page
  4. Concepts
    1. Using the JavaScript APIs
    2. User interface components
    3. Content scripts
    4. Match patterns
    5. Internationalization
    6. Content Security Policy
    7. Native messaging
  5. Porting
    1. Porting a Google Chrome extension
    2. Porting a legacy Firefox add-on
    3. Embedded WebExtensions
    4. Comparison with the Add-on SDK
    5. Comparison with XUL/XPCOM extensions
    6. Chrome incompatibilities
  6. Firefox workflow
    1. Temporary Installation in Firefox
    2. Debugging
    3. Getting started with web-ext
    4. web-ext command reference
    5. WebExtensions and the Add-on ID
    6. Publishing your WebExtension
  7. JavaScript APIs
    1. Browser support for JavaScript APIs
    2. alarms
    3. bookmarks
    4. browserAction
    5. browsingData
    6. commands
    7. contextMenus
    8. contextualIdentities
    9. cookies
    10. devtools.inspectedWindow
    11. devtools.network
    12. devtools.panels
    13. downloads
    14. events
    15. extension
    16. extensionTypes
    17. history
    18. i18n
    19. identity
    20. idle
    21. management
    22. notifications
    23. omnibox
    24. pageAction
    25. privacy
    26. runtime
    27. sessions
    28. sidebarAction
    29. storage
    30. tabs
    31. topSites
    32. webNavigation
    33. webRequest
    34. windows
  8. Manifest keys
    1. applications
    2. author
    3. background
    4. browser_action
    5. chrome_settings_overrides
    6. chrome_url_overrides
    7. commands
    8. content_scripts
    9. content_security_policy
    10. default_locale
    11. description
    12. developer
    13. devtools_page
    14. homepage_url
    15. icons
    16. manifest_version
    17. name
    18. omnibox
    19. options_ui
    20. page_action
    21. permissions
    22. protocol_handlers
    23. short_name
    24. sidebar_action
    25. version
    26. web_accessible_resources
  9. Add-on SDK
  10. Getting started
    1. Installation
    2. Getting started
    3. Troubleshooting
  11. High-Level APIs
    1. addon-page
    2. base64
    3. clipboard
    4. context-menu
    5. hotkeys
    6. indexed-db
    7. l10n
    8. notifications
    9. page-mod
    10. page-worker
    11. panel
    12. passwords
    13. private-browsing
    14. querystring
    15. request
    16. selection
    17. self
    18. simple-prefs
    19. simple-storage
    20. system
    21. tabs
    22. timers
    23. ui
    24. url
    25. webextension
    26. widget
    27. windows
  12. Low-Level APIs
    1. /loader
    2. chrome
    3. console/plain-text
    4. console/traceback
    5. content/content
    6. content/loader
    7. content/mod
    8. content/symbiont
    9. content/worker
    10. core/heritage
    11. core/namespace
    12. core/promise
    13. dev/panel
    14. event/core
    15. event/target
    16. frame/hidden-frame
    17. frame/utils
    18. fs/path
    19. io/byte-streams
    20. io/file
    21. io/text-streams
    22. lang/functional
    23. lang/type
    24. loader/cuddlefish
    25. loader/sandbox
    26. net/url
    27. net/xhr
    28. places/bookmarks
    29. places/favicon
    30. places/history
    31. platform/xpcom
    32. preferences/event-target
    33. preferences/service
    34. remote/child
    35. remote/parent
    36. stylesheet/style
    37. stylesheet/utils
    38. system/child_process
    39. system/environment
    40. system/events
    41. system/runtime
    42. system/unload
    43. system/xul-app
    44. tabs/utils
    45. test/assert
    46. test/harness
    47. test/httpd
    48. test/runner
    49. test/utils
    50. ui/button/action
    51. ui/button/toggle
    52. ui/frame
    53. ui/id
    54. ui/sidebar
    55. ui/toolbar
    56. util/array
    57. util/collection
    58. util/deprecate
    59. util/list
    60. util/match-pattern
    61. util/object
    62. util/uuid
    63. window/utils
  13. Firefox for Android
  14. Getting started
    1. Walkthrough
    2. Debugging
    3. Code snippets
  15. APIs
    1. Accounts.jsm
    2. BrowserApp
    3. HelperApps.jsm
    4. Home.jsm
    5. HomeProvider.jsm
    6. JavaAddonManager.jsm
    7. NativeWindow
    8. Notifications.jsm
    9. PageActions.jsm
    10. Prompt.jsm
    11. RuntimePermissions.jsm
    12. Snackbars.jsm
    13. Sound.jsm
    14. Tab
  16. Legacy
  17. Restartless extensions
    1. Overview
  18. Overlay extensions
    1. Overview
  19. Themes
  20. Lightweight themes
    1. Overview
  21. Complete themes
    1. Overview
  22. Publishing add-ons
  23. Guides
    1. Signing and distribution overview
    2. Submit an add-on
    3. Review policies
    4. Developer agreement
    5. Featured add-ons
    6. Contact addons.mozilla.org
  24. Community and support
  25. Channels
    1. Add-ons blog
    2. Add-on forums
    3. Stack Overflow
    4. Development newsgroup
    5. IRC Channel