Bug 1351608 - Comment out existing violations to no-unsanitize rule. r=standard8
☠☠ backed out by 36ea00c880db ☠ ☠
authorFrederik Braun <fbraun@mozilla.com>
Wed, 28 Jun 2017 12:50:38 -0700
changeset 366646 1cd9e27f0fa16bd65edc431ca37bbcd5ad72b3bd
parent 366645 d95016c5fc991c075d10b4591491d50650a7c487
child 366647 4ef2bbae969ad672b10c01adcfc229855c071536
push id45679
push usercbook@mozilla.com
push dateThu, 29 Jun 2017 13:53:31 +0000
treeherderautoland@365525f12a1f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstandard8
bugs1351608
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1351608 - Comment out existing violations to no-unsanitize rule. r=standard8
accessible/tests/mochitest/hittest/test_shadowroot.html
browser/base/content/aboutNetError.xhtml
browser/base/content/abouthome/aboutHome.js
browser/base/content/browser-media.js
browser/base/content/contentSearchUI.js
browser/base/content/test/siteIdentity/browser_bug906190.js
browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font.html
browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font2.html
browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_img.html
browser/base/content/test/webrtc/get_user_media.html
browser/base/content/test/webrtc/get_user_media_in_frame.html
browser/components/customizableui/CustomizableWidgets.jsm
browser/components/customizableui/CustomizeMode.jsm
browser/components/originattributes/test/browser/browser_sharedworker.js
browser/components/originattributes/test/browser/file_broadcastChannel.html
browser/components/places/tests/browser/pageopeningwindow.html
browser/components/preferences/in-content-new/findInPage.js
browser/components/resistfingerprinting/test/browser/file_navigator.html
browser/components/sessionstore/test/browser_459906.js
browser/components/syncedtabs/SyncedTabsDeckView.js
browser/extensions/onboarding/content/onboarding.js
browser/modules/ExtensionsUI.jsm
browser/modules/webrtcUI.jsm
devtools/client/inspector/markup/markup.js
devtools/client/shared/autocomplete-popup.js
devtools/client/shared/test/browser_templater_basic.js
devtools/client/shared/widgets/ColorWidget.js
devtools/client/shared/widgets/FilterWidget.js
devtools/client/shared/widgets/tooltip/HTMLTooltip.js
devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js
devtools/client/sourceeditor/editor.js
devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/head.js
devtools/client/webconsole/new-console-output/test/fixtures/stubs/networkEvent.js
devtools/client/webconsole/new-console-output/test/fixtures/stubs/pageError.js
devtools/server/actors/inspector.js
devtools/server/tests/mochitest/test_css-logic-specificity.html
mobile/android/chrome/content/config.js
mobile/android/tests/browser/robocop/robocop_boxes.html
mobile/android/tests/browser/robocop/robocop_input.html
npm-shrinkwrap.json
package.json
security/manager/ssl/tests/mochitest/mixedcontent/bug329869.js
security/manager/ssl/tests/mochitest/mixedcontent/iframe.html
security/manager/ssl/tests/mochitest/mixedcontent/iframe2.html
security/manager/ssl/tests/mochitest/stricttransportsecurity/nosts_bootstrap.html
security/manager/ssl/tests/mochitest/stricttransportsecurity/plain_bootstrap.html
security/manager/ssl/tests/mochitest/stricttransportsecurity/subdom_bootstrap.html
testing/talos/talos/generate-tart-xpi.html
testing/talos/talos/generate-tresize-xpi.html
testing/talos/talos/tests/a11y/dhtml.html
testing/talos/talos/tests/devtools/addon/content/addon-test-frontend.js
testing/talos/talos/tests/devtools/addon/content/damp.html
testing/talos/talos/tests/tart/addon/content/tart.html
toolkit/components/narrate/NarrateControls.jsm
toolkit/components/narrate/VoiceSelect.jsm
toolkit/components/passwordmgr/test/mochitest/test_formless_autofill.html
toolkit/components/passwordmgr/test/mochitest/test_formless_submit.html
toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation.html
toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation_negative.html
toolkit/components/passwordmgr/test/mochitest/test_password_field_autocomplete.html
toolkit/content/aboutTelemetry.js
toolkit/content/aboutwebrtc/aboutWebrtc.js
toolkit/content/plugins.html
toolkit/modules/sessionstore/FormData.jsm
toolkit/mozapps/extensions/content/extensions.js
--- a/accessible/tests/mochitest/hittest/test_shadowroot.html
+++ b/accessible/tests/mochitest/hittest/test_shadowroot.html
@@ -58,15 +58,16 @@
     // This routine adds the comment children of each 'component' to its
     // shadow root.
     var components = document.querySelectorAll('.components');
     for (var i = 0; i < components.length; i++) {
       var component = components[i];
       var shadow = component.createShadowRoot();
       for (var child = component.firstChild; child; child = child.nextSibling) {
         if (child.nodeType === 8)
+          // eslint-disable-next-line no-unsanitized/property
           shadow.innerHTML = child.data;
       }
     }
   </script>
 
 </body>
 </html>
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -172,21 +172,23 @@
         // defined, get the generic message
         var errTitle = document.getElementById("et_" + err);
         var errDesc  = document.getElementById("ed_" + err);
         if (!errTitle || !errDesc) {
           errTitle = document.getElementById("et_generic");
           errDesc  = document.getElementById("ed_generic");
         }
 
+        // eslint-disable-next-line no-unsanitized/property
         document.querySelector(".title-text").innerHTML = errTitle.innerHTML;
 
         var sd = document.getElementById("errorShortDescText");
         if (sd) {
           if (gIsCertError) {
+          // eslint-disable-next-line no-unsanitized/property
             sd.innerHTML = errDesc.innerHTML;
           } else {
             sd.textContent = getDescription();
           }
         }
         if (showCaptivePortalUI) {
           initPageCaptivePortal();
           return;
@@ -196,16 +198,17 @@
           return;
         }
         addAutofocus("errorTryAgain");
 
         document.body.className = "neterror";
 
         var ld = document.getElementById("errorLongDesc");
         if (ld) {
+        // eslint-disable-next-line no-unsanitized/property
           ld.innerHTML = errDesc.innerHTML;
         }
 
         if (err == "sslv3Used") {
           document.getElementById("learnMoreContainer").style.display = "block";
           let learnMoreLink = document.getElementById("learnMoreLink");
           learnMoreLink.href = "https://support.mozilla.org/kb/how-resolve-sslv3-error-messages-firefox";
           document.body.className = "certerror";
--- a/browser/base/content/abouthome/aboutHome.js
+++ b/browser/base/content/abouthome/aboutHome.js
@@ -329,16 +329,17 @@ function showSnippets() {
   }
   _snippetsShown = true;
 
   let snippets = gSnippetsMap.get("snippets");
   // If there are remotely fetched snippets, try to to show them.
   if (snippets) {
     // Injecting snippets can throw if they're invalid XML.
     try {
+      // eslint-disable-next-line no-unsanitized/property
       snippetsElt.innerHTML = snippets;
       // Scripts injected by innerHTML are inactive, so we have to relocate them
       // through DOM manipulation to activate their contents.
       Array.forEach(snippetsElt.getElementsByTagName("script"), function(elt) {
         let relocatedScript = document.createElement("script");
         relocatedScript.type = "text/javascript";
         relocatedScript.text = elt.text;
         elt.parentNode.replaceChild(relocatedScript, elt);
--- a/browser/base/content/browser-media.js
+++ b/browser/base/content/browser-media.js
@@ -119,16 +119,17 @@ var gEMEHandler = {
       });
     }
 
     let iconURL = "chrome://browser/skin/drm-icon.svg#chains-black";
 
     // Do a little dance to get rich content into the notification:
     let fragment = document.createDocumentFragment();
     let descriptionContainer = document.createElement("description");
+    // eslint-disable-next-line no-unsanitized/property
     descriptionContainer.innerHTML = message;
     while (descriptionContainer.childNodes.length) {
       fragment.appendChild(descriptionContainer.childNodes[0]);
     }
 
     box.appendNotification(fragment, notificationId, iconURL, box.PRIORITY_WARNING_MEDIUM,
                            buttons);
   },
--- a/browser/base/content/contentSearchUI.js
+++ b/browser/base/content/contentSearchUI.js
@@ -615,16 +615,17 @@ ContentSearchUIController.prototype = {
   },
 
   _updateSearchWithHeader() {
     if (!this._strings) {
       return;
     }
     let searchWithHeader = document.getElementById("contentSearchSearchWithHeader");
     if (this.input.value) {
+      // eslint-disable-next-line no-unsanitized/property
       searchWithHeader.innerHTML = this._strings.searchForSomethingWith;
       searchWithHeader.querySelector(".contentSearchSearchWithHeaderSearchText").textContent = this.input.value;
     } else {
       searchWithHeader.textContent = this._strings.searchWithHeader;
     }
   },
 
   _speculativeConnect() {
--- a/browser/base/content/test/siteIdentity/browser_bug906190.js
+++ b/browser/base/content/test/siteIdentity/browser_bug906190.js
@@ -35,16 +35,17 @@ async function doTest(parentTabSpec, chi
 
     // Wait for the script in the page to update the contents of the test div.
     let testDiv = content.document.getElementById("mctestdiv");
     await BrowserTestUtils.waitForCondition(
       () => testDiv.innerHTML == "Mixed Content Blocker disabled");
 
     // Add the link for the child tab to the page.
     let mainDiv = content.document.createElement("div");
+    // eslint-disable-next-line no-unsanitized/property
     mainDiv.innerHTML =
       '<p><a id="linkToOpenInNewTab" href="' + childTabSpec + '">Link</a></p>';
     content.document.body.appendChild(mainDiv);
 
     // Execute the test in the child tabs with the two methods to open it.
     for (let openFn of [simulateCtrlClick, simulateContextMenuOpenInTab]) {
       let promiseTabLoaded = waitForSomeTabToLoad();
       openFn(browser);
--- a/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font.html
+++ b/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font.html
@@ -30,16 +30,17 @@
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
    is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
 
    var blockedMixedDisplay = ui &&
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
    is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
 
    var newValue = "Verifying MCB does not trigger warning/error for an http page with https css that includes http font";
+   // eslint-disable-next-line no-unsanitized/property
    document.getElementById("testDiv").innerHTML = newValue;
   }
 </script>
 </head>
 <body onload="checkLoadStates()">
   <div class="testDiv" id="testDiv">
     Testing MCB does not trigger warning/error for an http page with https css that includes http font
   </div>
--- a/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font2.html
+++ b/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font2.html
@@ -31,16 +31,17 @@
    is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
 
    var blockedMixedDisplay = ui &&
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
    is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
 
    var newValue = "Verifying MCB does not trigger warning/error for an http page ";
     newValue += "with https css that imports another http css which includes http font";
+   // eslint-disable-next-line no-unsanitized/property
    document.getElementById("testDiv").innerHTML = newValue;
   }
 </script>
 </head>
 <body onload="checkLoadStates()">
   <div class="testDiv" id="testDiv">
     Testing MCB does not trigger warning/error for an http page with https css that imports another http css which includes http font
   </div>
--- a/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_img.html
+++ b/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_img.html
@@ -30,16 +30,17 @@
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
    is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
 
    var blockedMixedDisplay = ui &&
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
    is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
 
    var newValue = "Verifying MCB does not trigger warning/error for an http page with https css that includes http image";
+   // eslint-disable-next-line no-unsanitized/property
    document.getElementById("testDiv").innerHTML = newValue;
   }
 </script>
 </head>
 <body onload="checkLoadStates()">
   <div class="testDiv" id="testDiv">
     Testing MCB does not trigger warning/error for an http page with https css that includes http image
   </div>
--- a/browser/base/content/test/webrtc/get_user_media.html
+++ b/browser/base/content/test/webrtc/get_user_media.html
@@ -13,16 +13,17 @@ try {
   dump("audio: " + audioDevice + "\nvideo: " + videoDevice + "\n");
   useFakeStreams = false;
 } catch (e) {
   dump("TEST DEVICES: No test devices found (in media.{audio,video}_loopback_dev, using fake streams.\n");
   useFakeStreams = true;
 }
 
 function message(m) {
+  // eslint-disable-next-line no-unsanitized/property
   document.getElementById("message").innerHTML = m;
   window.parent.postMessage(m, "*");
 }
 
 var gStreams = [];
 
 function requestDevice(aAudio, aVideo, aShare, aBadDevice = false) {
   var opts = {video: aVideo, audio: aAudio};
--- a/browser/base/content/test/webrtc/get_user_media_in_frame.html
+++ b/browser/base/content/test/webrtc/get_user_media_in_frame.html
@@ -13,16 +13,17 @@ try {
   dump("audio: " + audioDevice + "\nvideo: " + videoDevice + "\n");
   useFakeStreams = false;
 } catch (e) {
   dump("TEST DEVICES: No test devices found (in media.{audio,video}_loopback_dev, using fake streams.\n");
   useFakeStreams = true;
 }
 
 function message(m) {
+  // eslint-disable-next-line no-unsanitized/property
   document.getElementById("message").innerHTML = m;
   window.parent.postMessage(m, "*");
 }
 
 var gStreams = [];
 
 function requestDevice(aAudio, aVideo, aShare) {
   var opts = {video: aVideo, audio: aAudio};
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -326,16 +326,17 @@ const CustomizableWidgets = [
         link.textContent = bundle.getString(`appMenuRemoteTabs.mobilePromo.${os}`);
         link.setAttribute("mobile-promo-os", os);
         link.className = "text-link remotetabs-promo-link";
         return link.outerHTML;
       });
       let promoParentElt = doc.getElementById("PanelUI-remotetabs-mobile-promo");
       // Put it all together...
       let contents = bundle.getFormattedString("appMenuRemoteTabs.mobilePromo.text2", formatArgs);
+      // eslint-disable-next-line no-unsanitized/property
       promoParentElt.innerHTML = contents;
       // We manually manage the "click" event to open the promo links because
       // allowing the "text-link" widget handle it has 2 problems: (1) it only
       // supports button 0 and (2) it's tricky to intercept when it does the
       // open and auto-close the panel. (1) can probably be fixed, but (2) is
       // trickier without hard-coding here the knowledge of exactly what buttons
       // it does support.
       // So we allow left and middle clicks to open the link in a new tab and
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -706,16 +706,17 @@ CustomizeMode.prototype = {
       return;
 
     let anchorNode = aAnchor || this.document.getElementById("customization-panelHolder");
     let messageNode = this.tipPanel.querySelector(".customization-tipPanel-contentMessage");
     if (!messageNode.childElementCount) {
       // Put the tip contents in the popup.
       let bundle = this.document.getElementById("bundle_browser");
       const kLabelClass = "customization-tipPanel-link";
+      // eslint-disable-next-line no-unsanitized/property
       messageNode.innerHTML = bundle.getFormattedString("customizeTips.tip0", [
         "<label class=\"customization-tipPanel-em\" value=\"" +
           bundle.getString("customizeTips.tip0.hint") + "\"/>",
         this.document.getElementById("bundle_brand").getString("brandShortName"),
         "<label class=\"" + kLabelClass + " text-link\" value=\"" +
         bundle.getString("customizeTips.tip0.learnMore") + "\"/>"
       ]);
 
--- a/browser/components/originattributes/test/browser/browser_sharedworker.js
+++ b/browser/components/originattributes/test/browser/browser_sharedworker.js
@@ -7,16 +7,17 @@ const TEST_PATH = TEST_DOMAIN + "browser
 const TEST_PAGE = TEST_PATH + "file_sharedworker.html";
 
 async function getResultFromSharedworker(aBrowser) {
   let response = await ContentTask.spawn(aBrowser, null, async function() {
     let worker = new content.SharedWorker("file_sharedworker.js", "isolationSharedWorkerTest");
 
     let result = await new Promise(resolve => {
       worker.port.onmessage = function(e) {
+        // eslint-disable-next-line no-unsanitized/property
         content.document.getElementById("display").innerHTML = e.data;
         resolve(e.data);
       };
     });
 
     return result;
   });
 
--- a/browser/components/originattributes/test/browser/file_broadcastChannel.html
+++ b/browser/components/originattributes/test/browser/file_broadcastChannel.html
@@ -5,12 +5,13 @@
   <title>Page broadcast channel creator for first party isolation</title>
 </head>
 <body>
   <div id="display" style="white-space:pre; font-family:monospace; display:inline;"></div>
   <iframe id="iframe" src="file_broadcastChanneliFrame.html"></iframe>>
 <script type="text/javascript">
 let bc = new BroadcastChannel("testBroadcastChannel");
 bc.onmessage = function(e) {
+  // eslint-disable-next-line no-unsanitized/property
   document.getElementById("display").innerHTML = e.data;
 };
 </script>
 </body>
--- a/browser/components/places/tests/browser/pageopeningwindow.html
+++ b/browser/components/places/tests/browser/pageopeningwindow.html
@@ -1,9 +1,11 @@
 <meta charset="UTF-8">
-Hi, I was opened via a <script>document.write(location.search ?
+Hi, I was opened via a <script>
+// eslint-disable-next-line no-unsanitized/method
+document.write(location.search ?
   "popup call from the opened window... uh oh, that shouldn't happen!" :
   "bookmarklet, and I will open a new window myself.")</script><br>
 <script>
   if (!location.search) {
     open(location.href + "?donotopen=true", "_blank");
   }
 </script>
--- a/browser/components/preferences/in-content-new/findInPage.js
+++ b/browser/components/preferences/in-content-new/findInPage.js
@@ -257,16 +257,17 @@ var gSearchResultsPane = {
 
         let strings = this.strings;
 
         document.getElementById("sorry-message").textContent = AppConstants.platform == "win" ?
           strings.getFormattedString("searchResults.sorryMessageWin", [this.query]) :
           strings.getFormattedString("searchResults.sorryMessageUnix", [this.query]);
         let helpUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") + "preferences";
         let brandName = document.getElementById("bundleBrand").getString("brandShortName");
+        // eslint-disable-next-line no-unsanitized/property
         document.getElementById("need-help").innerHTML =
           strings.getFormattedString("searchResults.needHelp2", [helpUrl, brandName]);
       } else {
         // Creating tooltips for all the instances found
         this.listSearchTooltips.forEach((anchorNode) => this.createSearchTooltip(anchorNode, this.query));
       }
     } else {
       this.searchResultsCategory.hidden = true;
--- a/browser/components/resistfingerprinting/test/browser/file_navigator.html
+++ b/browser/components/resistfingerprinting/test/browser/file_navigator.html
@@ -18,16 +18,17 @@
     result["vendor"] = navigator.vendor;
     result["vendorSub"] = navigator.vendorSub;
     result["mimeTypesLength"] = navigator.mimeTypes.length;
     result["pluginsLength"] = navigator.plugins.length;
     result["oscpu"] = navigator.oscpu;
     result["buildID"] = navigator.buildID;
     result["hardwareConcurrency"] = navigator.hardwareConcurrency;
 
+    // eslint-disable-next-line no-unsanitized/property
     document.getElementById("result").innerHTML = JSON.stringify(result);
   }
 </script>
 </head>
 <body onload="collect();">
 <p id="result"></p>
 </body>
 </html>
--- a/browser/components/sessionstore/test/browser_459906.js
+++ b/browser/components/sessionstore/test/browser_459906.js
@@ -15,16 +15,17 @@ function test() {
   let tab = BrowserTestUtils.addTab(gBrowser, testURL);
   tab.linkedBrowser.addEventListener("load", function(aEvent) {
     // wait for all frames to load completely
     if (frameCount++ < 2)
       return;
     tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
 
     let iframes = tab.linkedBrowser.contentWindow.frames;
+    // eslint-disable-next-line no-unsanitized/property
     iframes[1].document.body.innerHTML = uniqueValue;
 
     frameCount = 0;
     let tab2 = gBrowser.duplicateTab(tab);
     tab2.linkedBrowser.addEventListener("load", function(eventTab2) {
       // wait for all frames to load (and reload!) completely
       if (frameCount++ < 2)
         return;
--- a/browser/components/syncedtabs/SyncedTabsDeckView.js
+++ b/browser/components/syncedtabs/SyncedTabsDeckView.js
@@ -70,16 +70,17 @@ SyncedTabsDeckView.prototype = {
       let link = this._doc.createElement("a");
       link.textContent = bundle.getString(`appMenuRemoteTabs.mobilePromo.${os}`);
       link.className = `${os}-link text-link`;
       link.setAttribute("href", "#");
       return link.outerHTML;
     });
     // Put it all together...
     let contents = bundle.getFormattedString("appMenuRemoteTabs.mobilePromo.text2", formatArgs);
+    // eslint-disable-next-line no-unsanitized/property
     this.container.querySelector(".device-promo").innerHTML = contents;
   },
 
   destroy() {
     this._tabListComponent.uninit();
     this.container.remove();
   },
 
--- a/browser/extensions/onboarding/content/onboarding.js
+++ b/browser/extensions/onboarding/content/onboarding.js
@@ -158,16 +158,17 @@ var onboardingTours = [
         message: bundle.formatStringFromName("onboarding.notification.onboarding-tour-default-browser.message", [BRAND_SHORT_NAME], 1),
         button: bundle.GetStringFromName("onboarding.button.learnMore"),
       };
     },
     getPage(win) {
       let div = win.document.createElement("div");
       let defaultBrowserButtonId = win.matchMedia("(-moz-os-version: windows-win7)").matches ?
         "onboarding.tour-default-browser.win7.button" : "onboarding.tour-default-browser.button";
+      // eslint-disable-next-line no-unsanitized/property
       div.innerHTML = `
         <section class="onboarding-tour-description">
           <h1 data-l10n-id="onboarding.tour-default-browser.title"></h1>
           <p data-l10n-id="onboarding.tour-default-browser.description"></p>
         </section>
         <section class="onboarding-tour-content">
           <img src="resource://onboarding/img/figure_default.svg" />
         </section>
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -373,18 +373,20 @@ this.ExtensionsUI = {
 
     return result;
   },
 
   showPermissionsPrompt(browser, strings, icon, histkey) {
     function eventCallback(topic) {
       let doc = this.browser.ownerDocument;
       if (topic == "showing") {
+        // eslint-disable-next-line no-unsanitized/property
         doc.getElementById("addon-webext-perm-header").innerHTML = strings.header;
         let textEl = doc.getElementById("addon-webext-perm-text");
+        // eslint-disable-next-line no-unsanitized/property
         textEl.innerHTML = strings.text;
         textEl.hidden = !strings.text;
 
         let listIntroEl = doc.getElementById("addon-webext-perm-intro");
         listIntroEl.value = strings.listIntro;
         listIntroEl.hidden = (strings.msgs.length == 0);
 
         let list = doc.getElementById("addon-webext-perm-list");
@@ -431,16 +433,17 @@ this.ExtensionsUI = {
               this.histogram.add(histkey + "Rejected");
             }
             resolve(false);
           },
         },
       ];
 
       win.PopupNotifications.show(browser, "addon-webext-permissions", "",
+      // eslint-disable-next-line no-unsanitized/property
                                   "addons-notification-icon",
                                   action, secondaryActions, popupOptions);
     });
   },
 
   showInstallNotification(target, addon) {
     let win = target.ownerGlobal;
     let popups = win.PopupNotifications;
@@ -471,18 +474,20 @@ this.ExtensionsUI = {
                  "chrome://browser/skin/addons/addon-install-installed.svg";
       let options = {
         hideClose: true,
         timeout: Date.now() + 30000,
         popupIconURL: icon,
         eventCallback(topic) {
           if (topic == "showing") {
             let doc = this.browser.ownerDocument;
+        // eslint-disable-next-line no-unsanitized/property
             doc.getElementById("addon-installed-notification-header")
                .innerHTML = msg1;
+            // eslint-disable-next-line no-unsanitized/property
             doc.getElementById("addon-installed-notification-message")
                .innerHTML = msg2;
           } else if (topic == "dismissed") {
             resolve();
           }
         }
       };
 
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -631,16 +631,17 @@ function prompt(aBrowser, aRequest) {
               string = bundle.getFormattedString("getUserMedia.shareScreenWarning.message",
                                                  [learnMore]);
             } else {
               let brand =
                 doc.getElementById("bundle_brand").getString("brandShortName");
               string = bundle.getFormattedString("getUserMedia.shareFirefoxWarning.message",
                                                  [brand, learnMore]);
             }
+            // eslint-disable-next-line no-unsanitized/property
             warning.innerHTML = string;
           }
 
           let perms = Services.perms;
           let chromeUri = Services.io.newURI(doc.documentURI);
           perms.add(chromeUri, "MediaManagerVideo", perms.ALLOW_ACTION,
                     perms.EXPIRE_SESSION);
 
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -1383,16 +1383,17 @@ MarkupView.prototype = {
     if (!container) {
       return promise.reject();
     }
 
     let def = defer();
 
     let injectedNodes = [];
     container.undo.do(() => {
+      // eslint-disable-next-line no-unsanitized/method
       this.walker.insertAdjacentHTML(node, position, value).then(nodeArray => {
         injectedNodes = nodeArray.nodes;
         return nodeArray;
       }).then(def.resolve, def.reject);
     }, () => {
       this.walker.removeNodes(injectedNodes);
     });
 
--- a/devtools/client/shared/autocomplete-popup.js
+++ b/devtools/client/shared/autocomplete-popup.js
@@ -383,16 +383,17 @@ AutocompletePopup.prototype = {
 
     // Make sure the list clone is in the same document as the anchor.
     let anchorDoc = this._activeElement.ownerDocument;
     if (!this._listClone.parentNode || this._listClone.ownerDocument !== anchorDoc) {
       anchorDoc.documentElement.appendChild(this._listClone);
     }
 
     // Update the clone content to match the current list content.
+    // eslint-disable-next-line no-unsanitized/property
     this._listClone.innerHTML = this._list.innerHTML;
 
     this._activeElement.setAttribute("aria-activedescendant", id);
   },
 
   /**
    * Clear the aria-activedescendant attribute on the current active element.
    */
--- a/devtools/client/shared/test/browser_templater_basic.js
+++ b/devtools/client/shared/test/browser_templater_basic.js
@@ -24,16 +24,17 @@ var test = Task.async(function* () {
 });
 
 function runTest(index, host, doc) {
   let options = tests[index] = tests[index]();
   let holder = doc.createElement("div");
   holder.id = options.name;
   let body = doc.body;
   body.appendChild(holder);
+  // eslint-disable-next-line no-unsanitized/property
   holder.innerHTML = options.template;
 
   info("Running " + options.name);
   template(holder, options.data, options.options);
 
   if (typeof options.result == "string") {
     is(holder.innerHTML, options.result, options.name);
   } else {
--- a/devtools/client/shared/widgets/ColorWidget.js
+++ b/devtools/client/shared/widgets/ColorWidget.js
@@ -260,16 +260,17 @@ ColorWidget.prototype = {
   },
 
   initializeColorWidget: function () {
     let colorNameLabel = L10N.getStr("inspector.colorwidget.colorNameLabel");
     this.parentEl.innerHTML = "";
     this.element = this.parentEl.ownerDocument.createElementNS(XHTML_NS, "div");
 
     this.element.className = "colorwidget-container";
+    // eslint-disable-next-line no-unsanitized/property
     this.element.innerHTML = `
       <div class="colorwidget-top">
         <div class="colorwidget-fill"></div>
         <div class="colorwidget-top-inner">
           <div class="colorwidget-color colorwidget-box">
             <div class="colorwidget-sat">
               <div class="colorwidget-val">
                 <div class="colorwidget-dragger"></div>
--- a/devtools/client/shared/widgets/FilterWidget.js
+++ b/devtools/client/shared/widgets/FilterWidget.js
@@ -157,16 +157,17 @@ CSSFilterEditorWidget.prototype = {
   _initMarkup: function () {
     let filterListSelectPlaceholder =
       L10N.getStr("filterListSelectPlaceholder");
     let addNewFilterButton = L10N.getStr("addNewFilterButton");
     let presetsToggleButton = L10N.getStr("presetsToggleButton");
     let newPresetPlaceholder = L10N.getStr("newPresetPlaceholder");
     let savePresetButton = L10N.getStr("savePresetButton");
 
+    // eslint-disable-next-line no-unsanitized/property
     this.el.innerHTML = `
       <div class="filters-list">
         <div id="filters"></div>
         <div class="footer">
           <select value="">
             <option value="">${filterListSelectPlaceholder}</option>
           </select>
           <button id="add-filter" class="add">${addNewFilterButton}</button>
@@ -211,16 +212,17 @@ CSSFilterEditorWidget.prototype = {
   /**
     * Creates <option> elements for each filter definition
     * in filterList
     */
   _populateFilterSelect: function () {
     let select = this.filterSelect;
     filterList.forEach(filter => {
       let option = this.doc.createElementNS(XHTML_NS, "option");
+      // eslint-disable-next-line no-unsanitized/property
       option.innerHTML = option.value = filter.name;
       select.appendChild(option);
     });
   },
 
   /**
     * Creates a template for filter elements which is cloned and used in render
     */
@@ -623,16 +625,17 @@ CSSFilterEditorWidget.prototype = {
   },
 
   /**
    * Clears the list and renders filters, binding required events.
    * There are some delegated events bound in _addEventListeners method
    */
   render: function () {
     if (!this.filters.length) {
+  // eslint-disable-next-line no-unsanitized/property
       this.filtersList.innerHTML = `<p> ${L10N.getStr("emptyFilterList")} <br />
                                  ${L10N.getStr("addUsingList")} </p>`;
       this.emit("render");
       return;
     }
 
     this.filtersList.innerHTML = "";
 
@@ -704,16 +707,17 @@ CSSFilterEditorWidget.prototype = {
   renderPresets: function () {
     this.getPresets().then(presets => {
       // getPresets is async and the widget may be destroyed in between.
       if (!this.presetsList) {
         return;
       }
 
       if (!presets || !presets.length) {
+      // eslint-disable-next-line no-unsanitized/property
         this.presetsList.innerHTML = `<p>${L10N.getStr("emptyPresetList")}</p>`;
         this.emit("render");
         return;
       }
       let base = this._presetItemMarkup;
 
       this.presetsList.innerHTML = "";
 
--- a/devtools/client/shared/widgets/tooltip/HTMLTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/HTMLTooltip.js
@@ -501,16 +501,17 @@ HTMLTooltip.prototype = {
     container.classList.add("tooltip-container");
 
     let html = '<div class="tooltip-filler"></div>';
     html += '<div class="tooltip-panel"></div>';
 
     if (this.type === TYPE.ARROW) {
       html += '<div class="tooltip-arrow"></div>';
     }
+    // eslint-disable-next-line no-unsanitized/property
     container.innerHTML = html;
     return container;
   },
 
   _onClick: function (e) {
     if (this._isInTooltipContainer(e.target)) {
       return;
     }
--- a/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js
+++ b/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js
@@ -101,16 +101,17 @@ function setImageTooltip(tooltip, doc, i
   if (!hideDimensionLabel) {
     let label = naturalWidth + " \u00D7 " + naturalHeight;
     html += `
       <div style="height: ${LABEL_HEIGHT}px;
                   text-align: center;">
         <span class="theme-comment devtools-tooltip-caption">${label}</span>
       </div>`;
   }
+  // eslint-disable-next-line no-unsanitized/property
   div.innerHTML = html;
 
   // Calculate tooltip dimensions
   let height = imgHeight + 2 * IMAGE_PADDING;
   if (!hideDimensionLabel) {
     height += LABEL_HEIGHT;
   }
   let width = Math.max(CONTAINER_MIN_WIDTH, imgWidth + 2 * IMAGE_PADDING);
--- a/devtools/client/sourceeditor/editor.js
+++ b/devtools/client/sourceeditor/editor.js
@@ -814,16 +814,17 @@ Editor.prototype = {
     let cm = editors.get(this);
     let info = this.lineInfo(line);
     if (!info) {
       return;
     }
 
     let marker = cm.getWrapperElement().ownerDocument.createElement("div");
     marker.className = markerClass;
+    // eslint-disable-next-line no-unsanitized/property
     marker.innerHTML = content;
     cm.setGutterMarker(info.line, gutterName, marker);
   },
 
   /**
    * The reverse of addContentMarker. Removes any line's markers in the
    * specified gutter.
    */
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/head.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/head.js
@@ -301,16 +301,17 @@ function* generateConsoleApiStubs() {
       toolbox.target.client.addListener("consoleAPICall", listener);
     });
 
     yield ContentTask.spawn(
       gBrowser.selectedBrowser,
       [key, code],
       function ([subKey, subCode]) {
         let script = content.document.createElement("script");
+        // eslint-disable-next-line no-unsanitized/property
         script.innerHTML = `function triggerPacket() {${subCode}}`;
         content.document.body.appendChild(script);
         content.wrappedJSObject.triggerPacket();
         script.remove();
       }
     );
 
     yield received;
@@ -344,16 +345,17 @@ function* generateCssMessageStubs() {
       });
     });
 
     yield ContentTask.spawn(
       gBrowser.selectedBrowser,
       [key, code],
       function ([subKey, subCode]) {
         let style = content.document.createElement("style");
+        // eslint-disable-next-line no-unsanitized/property
         style.innerHTML = subCode;
         content.document.body.appendChild(style);
       }
     );
 
     yield received;
   }
 
@@ -433,16 +435,17 @@ function* generateNetworkEventStubs() {
       });
     });
 
     yield ContentTask.spawn(
       gBrowser.selectedBrowser,
       [key, code],
       function ([subKey, subCode]) {
         let script = content.document.createElement("script");
+        // eslint-disable-next-line no-unsanitized/property
         script.innerHTML = `function triggerPacket() {${subCode}}`;
         content.document.body.appendChild(script);
         content.wrappedJSObject.triggerPacket();
         script.remove();
       }
     );
 
     yield Promise.all([onNetwork, onNetworkUpdate]);
@@ -479,16 +482,17 @@ function* generatePageErrorStubs() {
       expectUncaughtException();
     }
 
     yield ContentTask.spawn(
       gBrowser.selectedBrowser,
       [key, code],
       function ([subKey, subCode]) {
         let script = content.document.createElement("script");
+        // eslint-disable-next-line no-unsanitized/property
         script.innerHTML = subCode;
         content.document.body.appendChild(script);
         script.remove();
       }
     );
 
     yield received;
   }
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stubs/networkEvent.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stubs/networkEvent.js
@@ -172,17 +172,17 @@ stubPackets.set("GET request", {
         "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
         "lineNumber": 3,
         "columnNumber": 1,
         "functionName": "triggerPacket",
         "asyncCause": null
       },
       {
         "filename": "resource://testing-common/content-task.js line 52 > eval",
-        "lineNumber": 7,
+        "lineNumber": 8,
         "columnNumber": 9,
         "functionName": null,
         "asyncCause": null
       },
       {
         "filename": "resource://testing-common/content-task.js",
         "lineNumber": 53,
         "columnNumber": 20,
@@ -245,17 +245,17 @@ stubPackets.set("XHR GET request", {
         "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
         "lineNumber": 4,
         "columnNumber": 1,
         "functionName": "triggerPacket",
         "asyncCause": null
       },
       {
         "filename": "resource://testing-common/content-task.js line 52 > eval",
-        "lineNumber": 7,
+        "lineNumber": 8,
         "columnNumber": 9,
         "functionName": null,
         "asyncCause": null
       },
       {
         "filename": "resource://testing-common/content-task.js",
         "lineNumber": 53,
         "columnNumber": 20,
@@ -318,17 +318,17 @@ stubPackets.set("XHR POST request", {
         "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
         "lineNumber": 4,
         "columnNumber": 1,
         "functionName": "triggerPacket",
         "asyncCause": null
       },
       {
         "filename": "resource://testing-common/content-task.js line 52 > eval",
-        "lineNumber": 7,
+        "lineNumber": 8,
         "columnNumber": 9,
         "functionName": null,
         "asyncCause": null
       },
       {
         "filename": "resource://testing-common/content-task.js",
         "lineNumber": 53,
         "columnNumber": 20,
--- a/devtools/client/webconsole/new-console-output/test/fixtures/stubs/pageError.js
+++ b/devtools/client/webconsole/new-console-output/test/fixtures/stubs/pageError.js
@@ -39,17 +39,17 @@ stubPreparedMessages.set("ReferenceError
     {
       "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
       "lineNumber": 9,
       "columnNumber": 3,
       "functionName": null
     },
     {
       "filename": "resource://testing-common/content-task.js line 52 > eval",
-      "lineNumber": 6,
+      "lineNumber": 7,
       "columnNumber": 9,
       "functionName": null
     },
     {
       "filename": "resource://testing-common/content-task.js",
       "lineNumber": 53,
       "columnNumber": 20,
       "functionName": null
@@ -75,17 +75,17 @@ stubPreparedMessages.set("SyntaxError: r
   "type": "log",
   "level": "error",
   "messageText": "SyntaxError: redeclaration of let a",
   "parameters": null,
   "repeatId": "{\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\",\"line\":2,\"column\":9},\"groupId\":null,\"indent\":0,\"level\":\"error\",\"messageText\":\"SyntaxError: redeclaration of let a\",\"parameters\":null,\"source\":\"javascript\",\"type\":\"log\",\"userProvidedStyles\":null}",
   "stacktrace": [
     {
       "filename": "resource://testing-common/content-task.js line 52 > eval",
-      "lineNumber": 6,
+      "lineNumber": 7,
       "columnNumber": 9,
       "functionName": null
     },
     {
       "filename": "resource://testing-common/content-task.js",
       "lineNumber": 53,
       "columnNumber": 20,
       "functionName": null
@@ -130,17 +130,17 @@ stubPreparedMessages.set("TypeError long
     {
       "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
       "lineNumber": 1,
       "columnNumber": 7,
       "functionName": null
     },
     {
       "filename": "resource://testing-common/content-task.js line 52 > eval",
-      "lineNumber": 6,
+      "lineNumber": 7,
       "columnNumber": 9,
       "functionName": null
     },
     {
       "filename": "resource://testing-common/content-task.js",
       "lineNumber": 53,
       "columnNumber": 20,
       "functionName": null
@@ -192,17 +192,17 @@ stubPackets.set("ReferenceError: asdf is
       {
         "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
         "lineNumber": 9,
         "columnNumber": 3,
         "functionName": null
       },
       {
         "filename": "resource://testing-common/content-task.js line 52 > eval",
-        "lineNumber": 6,
+        "lineNumber": 7,
         "columnNumber": 9,
         "functionName": null
       },
       {
         "filename": "resource://testing-common/content-task.js",
         "lineNumber": 53,
         "columnNumber": 20,
         "functionName": null
@@ -228,17 +228,17 @@ stubPackets.set("SyntaxError: redeclarat
     "error": false,
     "exception": true,
     "strict": false,
     "info": false,
     "private": false,
     "stacktrace": [
       {
         "filename": "resource://testing-common/content-task.js line 52 > eval",
-        "lineNumber": 6,
+        "lineNumber": 7,
         "columnNumber": 9,
         "functionName": null
       },
       {
         "filename": "resource://testing-common/content-task.js",
         "lineNumber": 53,
         "columnNumber": 20,
         "functionName": null
@@ -284,17 +284,17 @@ stubPackets.set("TypeError longString me
       {
         "filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
         "lineNumber": 1,
         "columnNumber": 7,
         "functionName": null
       },
       {
         "filename": "resource://testing-common/content-task.js line 52 > eval",
-        "lineNumber": 6,
+        "lineNumber": 7,
         "columnNumber": 9,
         "functionName": null
       },
       {
         "filename": "resource://testing-common/content-task.js",
         "lineNumber": 53,
         "columnNumber": 20,
         "functionName": null
--- a/devtools/server/actors/inspector.js
+++ b/devtools/server/actors/inspector.js
@@ -1992,16 +1992,17 @@ var WalkerActor = protocol.ActorClassWit
     if (isNodeDead(node)) {
       return;
     }
 
     let rawNode = node.rawNode;
     if (rawNode.nodeType !== rawNode.ownerDocument.ELEMENT_NODE) {
       throw new Error("Can only change innerHTML to element nodes");
     }
+    // eslint-disable-next-line no-unsanitized/property
     rawNode.innerHTML = value;
   },
 
   /**
    * Get a node's outerHTML property.
    *
    * @param {NodeActor} node The node.
    */
@@ -2031,22 +2032,24 @@ var WalkerActor = protocol.ActorClassWit
     // Special case for head and body.  Setting document.body.outerHTML
     // creates an extra <head> tag, and document.head.outerHTML creates
     // an extra <body>.  So instead we will call replaceChild with the
     // parsed DOM, assuming that they aren't trying to set both tags at once.
     if (rawNode.tagName === "BODY") {
       if (parsedDOM.head.innerHTML === "") {
         parentNode.replaceChild(parsedDOM.body, rawNode);
       } else {
+      // eslint-disable-next-line no-unsanitized/property
         rawNode.outerHTML = value;
       }
     } else if (rawNode.tagName === "HEAD") {
       if (parsedDOM.body.innerHTML === "") {
         parentNode.replaceChild(parsedDOM.head, rawNode);
       } else {
+        // eslint-disable-next-line no-unsanitized/property
         rawNode.outerHTML = value;
       }
     } else if (node.isDocumentElement()) {
       // Unable to set outerHTML on the document element.  Fall back by
       // setting attributes manually, then replace the body and head elements.
       let finalAttributeModifications = [];
       let attributeModifications = {};
       for (let attribute of rawNode.attributes) {
@@ -2060,16 +2063,17 @@ var WalkerActor = protocol.ActorClassWit
           attributeName: key,
           newValue: attributeModifications[key]
         });
       }
       node.modifyAttributes(finalAttributeModifications);
       rawNode.replaceChild(parsedDOM.head, rawNode.querySelector("head"));
       rawNode.replaceChild(parsedDOM.body, rawNode.querySelector("body"));
     } else {
+      // eslint-disable-next-line no-unsanitized/property
       rawNode.outerHTML = value;
     }
   },
 
   /**
    * Insert adjacent HTML to a node.
    *
    * @param {Node} node
--- a/devtools/server/tests/mochitest/test_css-logic-specificity.html
+++ b/devtools/server/tests/mochitest/test_css-logic-specificity.html
@@ -37,16 +37,17 @@ Test that css-logic calculates CSS speci
       {text: "bar:nth-child(n)", expected: 257},
       {text: "li::-moz-list-number", expected: 1},
       {text: "a:hover", expected: 257}
     ];
 
     function createDocument() {
       let text = TEST_DATA.map(i=>i.text).join(",");
       text = '<style type="text/css">' + text + " {color:red;}</style>";
+      // eslint-disable-next-line no-unsanitized/property
       document.body.innerHTML = text;
     }
 
     function getExpectedSpecificity(selectorText) {
       return TEST_DATA.filter(i => i.text === selectorText)[0].expected;
     }
 
     SimpleTest.waitForExplicitFinish();
--- a/mobile/android/chrome/content/config.js
+++ b/mobile/android/chrome/content/config.js
@@ -592,16 +592,17 @@ Pref.prototype = {
         function(aEvent) {
           AboutConfig.contextMenuLINode = AboutConfig.getLINodeForEvent(aEvent);
         }
       );
 
       this.li.setAttribute("contextmenu", "prefs-context-menu");
 
       // Create list item outline, bind to object actions
+      // eslint-disable-next-line no-unsanitized/property
       this.li.innerHTML =
         "<div class='pref-name' " +
             "onclick='AboutConfig.selectOrToggleBoolPref(event);'>" +
             this.name +
         "</div>" +
         "<div class='pref-item-line'>" +
           "<input class='pref-value' value='' " +
             "onblur='AboutConfig.setIntOrStringPref(event);' " +
--- a/mobile/android/tests/browser/robocop/robocop_boxes.html
+++ b/mobile/android/tests/browser/robocop/robocop_boxes.html
@@ -28,15 +28,16 @@ for (var y = 0; y < 2000; y += 100) {
     document.write("<div style='width: 2000px; height: 100px; margin: 0; padding: 0; border: none'>\n");
     for (var x = 0; x < 2000; x += 100) {
         var r = (Math.floor(x / 3) % 256);
         r = r & 0xF8;
         var g = (x + y) % 256;
         g = g & 0xFC;
         var b = (Math.floor(y / 3) % 256);
         b = b & 0xF8;
+        // eslint-disable-next-line no-unsanitized/method
         document.write("<div style='float: left; width: 100px; height: 100px; margin: 0; padding: 0; border: none; background-color: rgb(" + r + "," + g + "," + b + ")'> </div>\n");
     }
     document.write("</div>\n");
 }
 </script>
 </body>
 </html>
--- a/mobile/android/tests/browser/robocop/robocop_input.html
+++ b/mobile/android/tests/browser/robocop/robocop_input.html
@@ -114,16 +114,17 @@
         focus_content_editable: function(value) {
           getEditor = function() {
             return SpecialPowers.wrap(window).QueryInterface(
                 SpecialPowers.Ci.nsIInterfaceRequestor).getInterface(
                 SpecialPowers.Ci.nsIWebNavigation).QueryInterface(
                 SpecialPowers.Ci.nsIDocShell).editor;
           };
           setValue = function(val) {
+            // eslint-disable-next-line no-unsanitized/property
             contentEditable.innerHTML = val;
           };
           setSelection = function(pos) {
             window.getSelection().collapse(contentEditable.firstChild, pos);
           };
           setValue(value);
           contentEditable.focus();
         },
@@ -131,16 +132,17 @@
         focus_design_mode: function(value) {
           getEditor = function() {
             return SpecialPowers.wrap(designMode.contentWindow).QueryInterface(
                 SpecialPowers.Ci.nsIInterfaceRequestor).getInterface(
                 SpecialPowers.Ci.nsIWebNavigation).QueryInterface(
                 SpecialPowers.Ci.nsIDocShell).editor;
           };
           setValue = function(val) {
+          // eslint-disable-next-line no-unsanitized/property
             designMode.contentDocument.body.innerHTML = val;
           };
           setSelection = function(pos) {
             designMode.contentWindow.getSelection().collapse(
                 designMode.contentDocument.body.firstChild, pos);
           };
           setValue(value);
           designMode.contentWindow.focus();
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -210,30 +210,42 @@
       "version": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz",
       "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw="
     },
     "eslint-plugin-html": {
       "version": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-2.0.3.tgz",
       "integrity": "sha1-fImIOrDIX6XSi2ZqFKTpBqqQuJc="
     },
     "eslint-plugin-mozilla": {
-      "version": "file:tools\\lint\\eslint\\eslint-plugin-mozilla"
+      "version": "file:tools/lint/eslint/eslint-plugin-mozilla",
+      "dependencies": {
+        "eslint-plugin-no-unsanitized": {
+          "version": "2.0.1",
+          "bundled": true
+        }
+      }
+    },
+    "eslint-plugin-no-unsanitized": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-2.0.1.tgz",
+      "integrity": "sha1-yt7dDQrRfI3FIm23/4hATlmo1n8=",
+      "dev": true
     },
     "eslint-plugin-react": {
       "version": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz",
       "integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=",
       "dependencies": {
         "doctrine": {
           "version": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
           "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo="
         }
       }
     },
     "eslint-plugin-spidermonkey-js": {
-      "version": "file:tools\\lint\\eslint\\eslint-plugin-spidermonkey-js"
+      "version": "file:tools/lint/eslint/eslint-plugin-spidermonkey-js"
     },
     "espree": {
       "version": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz",
       "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q="
     },
     "esprima": {
       "version": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
       "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
--- a/package.json
+++ b/package.json
@@ -5,15 +5,17 @@
   "license": "MPL-2.0",
   "dependencies": {
     "escope": "^3.6.0",
     "eslint": "3.19.0",
     "eslint-plugin-html": "2.0.3",
     "eslint-plugin-mozilla": "file:tools/lint/eslint/eslint-plugin-mozilla",
     "eslint-plugin-react": "6.10.3",
     "eslint-plugin-spidermonkey-js": "file:tools/lint/eslint/eslint-plugin-spidermonkey-js",
-    "eslint-plugin-no-unsanitized": "2.0.1",
     "espree": "^3.4.0",
     "estraverse": "^4.2.0",
     "ini-parser": "^0.0.2",
     "sax": "^1.2.2"
+  },
+  "devDependencies": {
+    "eslint-plugin-no-unsanitized": "^2.0.1"
   }
 }
--- a/security/manager/ssl/tests/mochitest/mixedcontent/bug329869.js
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/bug329869.js
@@ -1,7 +1,8 @@
 /* import-globals-from mixedContentTest.js */
 "use strict";
 
 document.open();
+// eslint-disable-next-line no-unsanitized/method
 document.write("This is insecure XSS script " + document.cookie);
 isSecurityState("broken", "security broken after document write from unsecure script");
 finish();
--- a/security/manager/ssl/tests/mochitest/mixedcontent/iframe.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/iframe.html
@@ -2,12 +2,13 @@
 <html>
 <head>
 </head>
 
 <body>
   This is frame 1: 
   <script>
     "use strict";
+    // eslint-disable-next-line no-unsanitized/method
     document.write(location.href);
   </script>
 </body>
 </html>
--- a/security/manager/ssl/tests/mochitest/mixedcontent/iframe2.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/iframe2.html
@@ -2,13 +2,14 @@
 <html>
 <head>
 </head>
 
 <body>
   This is frame 2: 
   <script>
     "use strict";
+    // eslint-disable-next-line no-unsanitized/method
     document.write(location.href);
   </script>
   <iframe src="http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframe.html"></iframe>
 </body>
 </html>
--- a/security/manager/ssl/tests/mochitest/stricttransportsecurity/nosts_bootstrap.html
+++ b/security/manager/ssl/tests/mochitest/stricttransportsecurity/nosts_bootstrap.html
@@ -14,13 +14,14 @@
                                      "http://mochi.test:8888");
       });
     </script>
   </head>
   <body>
     <!-- This frame should be loaded over HTTPS to set the STS header. -->
     This frame was loaded using 
     <script>
+      // eslint-disable-next-line no-unsanitized/method
       document.write(document.location.protocol);
     </script>
     and set the STS header to force this site and allow subdomain upgrading.
   </body>
 </html>
--- a/security/manager/ssl/tests/mochitest/stricttransportsecurity/plain_bootstrap.html
+++ b/security/manager/ssl/tests/mochitest/stricttransportsecurity/plain_bootstrap.html
@@ -14,13 +14,14 @@
                                      "http://mochi.test:8888");
       });
     </script>
   </head>
   <body>
     <!-- This frame should be loaded over HTTPS to set the STS header. -->
     This frame was loaded using 
     <script>
+      // eslint-disable-next-line no-unsanitized/method
       document.write(document.location.protocol);
     </script>
     and set the STS header to force this site and allow subdomain upgrading.
   </body>
 </html>
--- a/security/manager/ssl/tests/mochitest/stricttransportsecurity/subdom_bootstrap.html
+++ b/security/manager/ssl/tests/mochitest/stricttransportsecurity/subdom_bootstrap.html
@@ -14,13 +14,14 @@
                                      "http://mochi.test:8888");
       });
     </script>
   </head>
   <body>
     <!-- This frame should be loaded over HTTPS to set the STS header. -->
     This frame was loaded using 
     <script>
+      // eslint-disable-next-line no-unsanitized/method
       document.write(document.location.protocol);
     </script>
     and set the STS header to force this site and allow subdomain upgrading.
   </body>
 </html>
--- a/testing/talos/talos/generate-tart-xpi.html
+++ b/testing/talos/talos/generate-tart-xpi.html
@@ -24,23 +24,27 @@
       "content/blank.icon.html",
       "content/Profiler.js",
       "content/tab-min-width-1px.css"
     ];
 
     function triggerBuildXpi() {
       function $(id) { return document.getElementById(id); }
 
+      // eslint-disable-next-line no-unsanitized/property
       $("status-text").innerHTML = "Preparing ...";
       $("result").style.display = "none";
       $("status").style.display = "inline";
 
       createXpiDataUri(base, files, {
+
+        // eslint-disable-next-line no-unsanitized/property
         onprogress(p) { $("status-text").innerHTML = "Preparing ... " + p.toFixed(0) + "%"; },
 
+        // eslint-disable-next-line no-unsanitized/property
         onerror(e) { $("status-text").innerHTML = "Oops, couldn't generate XPI. Reload to retry.<br/>" + e; },
 
         onsuccess(u) {
  $("xpi-link").href = u;
                               $("status").style.display = "none";
                               $("result").style.display = "inline";
 }
       });
--- a/testing/talos/talos/generate-tresize-xpi.html
+++ b/testing/talos/talos/generate-tresize-xpi.html
@@ -26,18 +26,21 @@
     function triggerBuildXpi() {
       function $(id) { return document.getElementById(id); }
 
       $("status-text").innerHTML = "Preparing ...";
       $("result").style.display = "none";
       $("status").style.display = "inline";
 
       createXpiDataUri(base, files, {
+
+        // eslint-disable-next-line no-unsanitized/property
         onprogress(p) { $("status-text").innerHTML = "Preparing ... " + p.toFixed(0) + "%"; },
 
+        // eslint-disable-next-line no-unsanitized/property
         onerror(e) { $("status-text").innerHTML = "Oops, couldn't generate XPI. Reload to retry.<br/>" + e; },
 
         onsuccess(u) {
  $("xpi-link").href = u;
                               $("status").style.display = "none";
                               $("result").style.display = "inline";
 }
       });
--- a/testing/talos/talos/tests/a11y/dhtml.html
+++ b/testing/talos/talos/tests/a11y/dhtml.html
@@ -26,16 +26,18 @@
     }
     for (i = 0; i < 2000; i++) {
       div = document.createElement("div");
       div.innerHTML = "<ul><li>foo<ul><li>bar</li></ul></li><li>baz</li></ul>";
       container.insertBefore(div, lastchild);
     }
     for (i = 0; i < 2000; i++) {
       div = document.createElement("div");
+
+      // eslint-disable-next-line no-unsanitized/property
       div.innerHTML = "<div role='progressbar'>progressbar</div>" +
                       "<span id='span" + i + "'>cb</span>";
       container.appendChild(div);
     }
     document.documentElement.offsetLeft; // flush layout
     setTimeout(postProcessingRecord, 0, start);
   }
 
--- a/testing/talos/talos/tests/devtools/addon/content/addon-test-frontend.js
+++ b/testing/talos/talos/tests/devtools/addon/content/addon-test-frontend.js
@@ -95,16 +95,18 @@ function doneTest(dispResult) {
       for (var s in stats) {
         if (s.indexOf(".half") >= 0 )
           dispStats += "<br/>";
         dispStats += s + "&nbsp;&nbsp;&nbsp;&nbsp;Average (" + stats[s].length + "): " + average(stats[s]).toFixed(2) + " stddev: " + stddev(stats[s]).toFixed(2) + "<br/>";
       }
 
       dispStats += "<hr/><b>Individual animations</b>:<br/>";
     }
+
+    // eslint-disable-next-line no-unsanitized/property
     $("run-results").innerHTML = "<hr/><br/>Results <button onclick='toClipboard(lastResults)'>[ Copy to clipboard as JSON ]</button>:<br/>" + dispStats + dispResult.join("<br/>");
   }
 }
 
 function triggerStart() {
   updateConfig();
   $("hide-during-run").style.display = "none";
   $("show-during-run").style.display = "block";
--- a/testing/talos/talos/tests/devtools/addon/content/damp.html
+++ b/testing/talos/talos/tests/devtools/addon/content/damp.html
@@ -62,16 +62,18 @@ function updateConfig() {
 
 Utilities:
   <a href="pages/simple.html">simple page</a>&nbsp;&nbsp;&nbsp;
   <a href="http://localhost/tests/tp5n/bild.de/www.bild.de/index.html">complicated page</a>&nbsp;&nbsp;&nbsp;
 <br/><br/>
 <b>Configure DAMP</b> (CTRL-F5 to reset to talos defaults) <button type="button" onclick="deselectAll()">Deselect all tests</button><br/>
 <script>
   for (var test in defaultConfig.subtests) {
+
+    // eslint-disable-next-line no-unsanitized/method
     document.write('<input type="checkbox" id="subtest-' + test + '" ' + (defaultConfig.subtests[test] ? "" : "un") + "checked>"
                   + test + "</input>"
                   + '<span style="color:grey">&nbsp;&nbsp;&nbsp;' + testsInfo[test] + "</span>"
                   + "<br/>");
   }
 </script>
   <br/>
   Repeat: <input id="repeat" type="text" size=2 value="1" onchange="updateConfig()"/> times<br/>
--- a/testing/talos/talos/tests/tart/addon/content/tart.html
+++ b/testing/talos/talos/tests/tart/addon/content/tart.html
@@ -108,16 +108,18 @@ function doneTest(dispResult) {
       for (var s in stats) {
         if (s.indexOf(".half") >= 0 )
           dispStats += "<br/>";
         dispStats += s + "&nbsp;&nbsp;&nbsp;&nbsp;Average (" + stats[s].length + "): " + average(stats[s]).toFixed(2) + " stddev: " + stddev(stats[s]).toFixed(2) + "<br/>";
       }
 
       dispStats += "<hr/><b>Individual animations</b>:<br/>";
     }
+
+    // eslint-disable-next-line no-unsanitized/property
     $("run-results").innerHTML = "<hr/><br/>Results <button onclick='toClipboard(lastResults)'>[ Copy to clipboard as JSON ]</button>:<br/>" + dispStats + dispResult.join("<br/>");
   }
 }
 
 var config = {subtests: [], repeat: 1}; // Empty subtests interpreted as all subtests, since otherwise meaningless.
 
 function triggerStart() {
   updateConfig();
@@ -259,16 +261,18 @@ addEventListener("load", init);
 
 Utilities:
   <a href="blank.icon.html">blank with icon</a>&nbsp;&nbsp;&nbsp;
   <a href="about:config?filter=/newtab|_rate|devP|offmain|docshell.event_starvation_delay_hint|rce-en/">about:config (already filtered with relevant prefs)</a>
 <br/><br/>
 <b>Configure TART</b> (CTRL-F5 to reset to talos defaults) <button type="button" onclick="deselectAll()">Deselect all tests</button><br/>
 <script>
   for (var test in defaultConfig.subtests) {
+
+    // eslint-disable-next-line no-unsanitized/method
     document.write('<input type="checkbox" id="subtest-' + test + '" ' + (defaultConfig.subtests[test] ? "" : "un") + "checked>"
                   + test + "</input>"
                   + '<span style="color:grey">&nbsp;&nbsp;&nbsp;' + testsInfo[test] + "</span>"
                   + "<br/>");
   }
   $("subtest-simple3open3closeDpiCurrent").checked = false; // Disabled by default for talos
 </script>
   <br/>
--- a/toolkit/components/narrate/NarrateControls.jsm
+++ b/toolkit/components/narrate/NarrateControls.jsm
@@ -37,16 +37,17 @@ function NarrateControls(mm, win, langua
     return result;
   }
 
   let dropdown = win.document.createElement("ul");
   dropdown.className = "dropdown";
   dropdown.id = "narrate-dropdown";
   // We need inline svg here for the animation to work (bug 908634 & 1190881).
   // The style animation can't be scoped (bug 830056).
+  // eslint-disable-next-line no-unsanitized/property
   dropdown.innerHTML =
     localize`<style scoped>
       @import url("chrome://global/skin/narrateControls.css");
     </style>
     <li>
        <button class="dropdown-toggle button" id="narrate-toggle"
                title="${"narrate"}" hidden>
          <svg xmlns="http://www.w3.org/2000/svg"
--- a/toolkit/components/narrate/VoiceSelect.jsm
+++ b/toolkit/components/narrate/VoiceSelect.jsm
@@ -8,16 +8,17 @@ const Cu = Components.utils;
 
 this.EXPORTED_SYMBOLS = ["VoiceSelect"];
 
 function VoiceSelect(win, label) {
   this._winRef = Cu.getWeakReference(win);
 
   let element = win.document.createElement("div");
   element.classList.add("voiceselect");
+  // eslint-disable-next-line no-unsanitized/property
   element.innerHTML =
    `<button class="select-toggle" aria-controls="voice-options">
       <span class="label">${label}</span> <span class="current-voice"></span>
     </button>
     <div class="options" id="voice-options" role="listbox"></div>`;
 
   this._elementRef = Cu.getWeakReference(element);
 
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_autofill.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_autofill.html
@@ -116,16 +116,17 @@ add_task(async function test() {
 
   for (let tc of TESTCASES) {
     info("Starting testcase: " + JSON.stringify(tc));
 
     let numFormLikesExpected = tc.expectedFormCount || 1;
 
     let processedFormPromise = promiseFormsProcessed(numFormLikesExpected);
 
+    // eslint-disable-next-line no-unsanitized/property
     frameDoc.documentElement.innerHTML = tc.document;
     info("waiting for " + numFormLikesExpected + " processed form(s)");
     await processedFormPromise;
 
     let testInputs = frameDoc.documentElement.querySelectorAll("input");
     is(testInputs.length, tc.expectedInputValues.length, "Check number of inputs");
     for (let i = 0; i < tc.expectedInputValues.length; i++) {
       let expectedValue = tc.expectedInputValues[i];
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_submit.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_submit.html
@@ -135,16 +135,17 @@ function getSubmitMessage() {
 }
 
 add_task(async function test() {
   let loginFrame = document.getElementById("loginFrame");
   let frameDoc = loginFrame.contentWindow.document;
 
   for (let tc of TESTCASES) {
     info("Starting testcase: " + JSON.stringify(tc));
+    // eslint-disable-next-line no-unsanitized/property
     frameDoc.documentElement.innerHTML = tc.document;
     let inputForFormLike = frameDoc.querySelectorAll("input")[tc.inputIndexForFormLike];
 
     let formLike = LoginFormFactory.createFromField(inputForFormLike);
 
     info("Calling _onFormSubmit with FormLike");
     let processedPromise = getSubmitMessage();
     LoginManagerContent._onFormSubmit(formLike);
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation.html
@@ -143,16 +143,17 @@ add_task(async function test() {
         loginFrame.addEventListener("load", function() {
           resolve();
         }, {once: true});
       });
       loginFrame.src = DEFAULT_ORIGIN + "/tests/toolkit/components/passwordmgr/test/mochitest/blank.html";
       await loadedPromise;
 
       let frameDoc = SpecialPowers.wrap(loginFrame.contentWindow).document;
+      // eslint-disable-next-line no-unsanitized/property
       frameDoc.documentElement.innerHTML = tc.document;
       // Wait for the form to be processed before trying to submit.
       await promiseFormsProcessed();
       let processedPromise = getSubmitMessage();
       info("Running " + scriptName + " script to cause a submission");
       frameDoc.defaultView.eval(SCRIPTS[scriptName]);
 
       let submittedResult = await processedPromise;
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation_negative.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation_negative.html
@@ -96,16 +96,17 @@ add_task(async function test() {
         loginFrame.addEventListener("load", function() {
           resolve();
         }, {once: true});
       });
       loginFrame.src = DEFAULT_ORIGIN + "/tests/toolkit/components/passwordmgr/test/mochitest/blank.html";
       await loadedPromise;
 
       let frameDoc = SpecialPowers.wrap(loginFrame.contentWindow).document;
+      // eslint-disable-next-line no-unsanitized/property
       frameDoc.documentElement.innerHTML = tc.document;
 
       // Wait for the form to be processed before trying to submit.
       await promiseFormsProcessed();
 
       info("Running " + scriptName + " script to check for a submission");
       frameDoc.defaultView.eval(SCRIPTS[scriptName]);
 
--- a/toolkit/components/passwordmgr/test/mochitest/test_password_field_autocomplete.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_password_field_autocomplete.html
@@ -108,16 +108,17 @@ const shiftModifier = SpecialPowers.Ci.n
 // Restore the form to the default state.
 async function reinitializeForm(index) {
   // Using innerHTML is for creating the autocomplete popup again, so the
   // preference value will be applied to the constructor of
   // UserAutoCompleteResult.
   let form = document.getElementById("form" + index);
   let temp = form.innerHTML;
   form.innerHTML = "";
+  // eslint-disable-next-line no-unsanitized/property
   form.innerHTML = temp;
 
   await new Promise(resolve => {
     let observer = SpecialPowers.wrapCallback(() => {
       SpecialPowers.removeObserver(observer, "passwordmgr-processed-form");
       resolve();
     });
     SpecialPowers.addObserver(observer, "passwordmgr-processed-form");
--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -261,16 +261,18 @@ var Settings = {
    */
   render() {
     let homeExplanation = document.getElementById("home-explanation");
     let fhrEnabled = this.getStatusStringForSetting(this.SETTINGS[0]);
     let extendedEnabled = this.getStatusStringForSetting(this.SETTINGS[1]);
     let parameters = [fhrEnabled, extendedEnabled].map(this.convertStringToLink);
 
     let explanation = bundle.formatStringFromName("homeExplanation", parameters, 2);
+
+    // eslint-disable-next-line no-unsanitized/property
     homeExplanation.innerHTML = explanation;
     this.attachObservers()
   },
 
   convertStringToLink(string) {
     return "<a href=\"\" class=\"change-data-choices-link\">" + string + "</a>";
   },
 };
@@ -330,16 +332,18 @@ var PingPicker = {
 
   render() {
     let pings = bundle.GetStringFromName("pingExplanationLink");
     let pingLink = "<a href=\"http://gecko.readthedocs.io/en/latest/toolkit/components/telemetry/telemetry/concepts/pings.html\">&quot;" + pings + "&quot;</a>";
     let pingName = "<span class=\"change-ping\">" + this._getSelectedPingName() + "</span>";
 
     let explanation = bundle.formatStringFromName("pingExplanation", [pingLink, pingName], 2);
     let pingExplanation = document.getElementById("ping-explanation");
+
+    // eslint-disable-next-line no-unsanitized/property
     pingExplanation.innerHTML = explanation;
     GenericSubsection.deleteAllSubSections();
   },
 
   async update() {
     let viewCurrent = document.getElementById("ping-source-current").checked;
     let currentChanged = viewCurrent !== this.viewCurrentPingData;
     this.viewCurrentPingData = viewCurrent;
--- a/toolkit/content/aboutwebrtc/aboutWebrtc.js
+++ b/toolkit/content/aboutwebrtc/aboutWebrtc.js
@@ -135,16 +135,17 @@ Control.prototype = {
   get message() {
     return this._messageVal;
   },
 
   update() {
     this.ctrl.textContent = this._label;
 
     if (this._message) {
+      // eslint-disable-next-line no-unsanitized/property
       this.msg.innerHTML =
         `<span class="info-label">${this._messageHeader}:</span> ${this._message}`;
     } else {
       this.msg.innerHTML = null;
     }
   },
 
   onClick(event) {
@@ -300,16 +301,17 @@ var AboutWebRTC = {
     this._content = parent;
     this._setData(data);
 
     if (data.error) {
       let msg = document.createElement("h3");
       msg.textContent = getString("cannot_retrieve_log");
       parent.appendChild(msg);
       msg = document.createElement("p");
+      // eslint-disable-next-line no-unsanitized/property
       msg.innerHTML = `${data.error.name}: ${data.error.message}`;
       parent.appendChild(msg);
       return;
     }
 
     this._peerConnections = this.renderPeerConnections();
     this._connectionLog = this.renderConnectionLog();
     this._content.appendChild(this._peerConnections);
--- a/toolkit/content/plugins.html
+++ b/toolkit/content/plugins.html
@@ -10,16 +10,17 @@
   "use strict";
 
   Components.utils.import("resource://gre/modules/Services.jsm");
 
   var Ci = Components.interfaces;
   var strBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
   var pluginsbundle = strBundleService.createBundle("chrome://global/locale/plugins.properties");
 
+  // eslint-disable-next-line no-unsanitized/method
   document.writeln("<title>" + pluginsbundle.GetStringFromName("title_label") + "<\/title>");
 </script>
 <link rel="stylesheet" type="text/css" href="chrome://global/content/plugins.css">
 <link rel="stylesheet" type="text/css" href="chrome://global/skin/plugins.css">
 </head>
 <body>
 <div id="outside">
 <script type="application/javascript">
--- a/toolkit/modules/sessionstore/FormData.jsm
+++ b/toolkit/modules/sessionstore/FormData.jsm
@@ -199,16 +199,17 @@ var FormDataInternal = {
         generatedCount++;
         ret.xpath = ret.xpath || {};
         ret.xpath[XPathGenerator.generate(node)] = value;
       }
     }
 
     // designMode is undefined e.g. for XUL documents (as about:config)
     if ((doc.designMode || "") == "on" && doc.body) {
+      // eslint-disable-next-line no-unsanitized/property
       ret.innerHTML = doc.body.innerHTML;
     }
 
     // Return |null| if no form data has been found.
     if (Object.keys(ret).length === 0) {
       return null;
     }
 
@@ -256,16 +257,17 @@ var FormDataInternal = {
 
     if ("xpath" in data) {
       let retrieveNode = xpath => XPathGenerator.resolve(doc, xpath);
       this.restoreManyInputValues(data.xpath, retrieveNode);
     }
 
     if ("innerHTML" in data) {
       if (doc.body && doc.designMode == "on") {
+      // eslint-disable-next-line no-unsanitized/property
         doc.body.innerHTML = data.innerHTML;
         this.fireEvent(doc.body, "input");
       }
     }
   },
 
   /**
    * Iterates the given form data, retrieving nodes for all the keys and
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -3248,16 +3248,17 @@ var gDetailView = {
     desc.textContent = aAddon.description;
 
     var fullDesc = document.getElementById("detail-fulldesc");
     if (aAddon.fullDescription) {
       // The following is part of an awful hack to include the licenses for GMP
       // plugins without having bug 624602 fixed yet, and intentionally ignores
       // localisation.
       if (aAddon.isGMPlugin) {
+        // eslint-disable-next-line no-unsanitized/property
         fullDesc.innerHTML = aAddon.fullDescription;
       } else {
         fullDesc.textContent = aAddon.fullDescription;
       }
 
       fullDesc.hidden = false;
     } else {
       fullDesc.hidden = true;