Firefox OS uses some automation to spot security errors throughout the development & build process. This article aims to documents how to work with those.
ESLint Security Checks in Firefox OS Gaia
Firefox OS Gaia uses ESLint to perform some basic security checks. We use https://github.com/mozfreddyb/eslint-plugin-no-unsafe-innerhtml. These checks are built into the Makefile as well as the git commit hook. The idea of these checks is to ensure that certain provably insecure coding patterns are avoided in our code base. We encourage developers to use the sanitizer.js library in gaia shared.
Unsafe assignment to innerHTML spotted
Fixing the test error
This error message suggests that you are using an unsafe coding pattern. Please do not assign variables to innerHTML, if at all possible. The new way requires the sanitizer.js library:
// if not included in the current project, you need require the sanitizer.js library from shared/js/ foo.innerHTML = Sanitizer.escapeHTML`<a href="${link}">click</a>`
Ignoring the test failure
If you can not apply this new coding style, please see below on how to get help.
Unsafe call to insertAdjacentHTML spotted
Fixing the test error
This error message suggests that you are using an unsafe coding pattern. Please do not simply call insertAdjacentHTML with a pure variable parameter. The new way requires the sanitizer.js library:
// if not included in the current project, you need require the sanitizer.js library from shared/js/ node.insertAdjacentHTML('afterend', Sanitizer.escapeHTML`<a href="${link}">click</a>`);
Ignoring the test failure
If you can not apply this new coding style, please see below on how to get help.
Storing and re-using the escaped HTML
The sanitizer has two basic usages. The first one is explained above, where we try to fix the most common errors. If you really need to generate your HTML somewhere else and e.g. cache it, you won't be able to run `escapeHTML` on a string that still carries the distinction between static HTML and user inputs. Thus, there is another feature in Sanitizer that allows you to create an object that contains escaped HTML which is guaranteed to be safe and thus allowed for direct innerHTML assignments (and insertAdjacentHTML calls): createSafeHTML and unwrapSafeHTML
// create the HTML object for later usage function storeGreeting(username) { var safeHTML = Sanitizer.createSafeHTML`<p>Hello ${username}</p>`; cache.store('greeting', safeHTML) } // re-use the existing safe-HTML object function useGreeting(domNode) { var htmlObj = cache.retrieve('greeting'); domNode.innerHTML = Sanitizer.unwrapSafeHTML(htmlObj); }
What if the new pattern can not be applied
If you cannot apply the escapeHTML pattern, try to work with the createSafeHTML and unwrapSafeHTML flow. If this does not work, don't worry. Every rule has its exceptions. If you think your example is not unsafe, you can file a bug that blocks against bug 1155131. Even better, you can submit a pull request and improve our automation, so that it will no longer complain about scripts like yours.
If you want your unsafe example to be discussed further even though it is unsafe, please raise this with the Firefox OS Security Team by requesting the sec-review? flag on your implementation bug towards [email protected].
Implementation Details
Related links
- implementation of our sanitizer – https://bugzilla.mozilla.org/show_bug.cgi?id=1155131
- Bringing ESLint into our source base (including the commit hook) – https://bugzilla.mozilla.org/show_bug.cgi?id=115966
- ESLint plugin to check the use of our sanitizer – https://github.com/mozfreddyb/eslint-plugin-no-unsafe-innerhtml