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 601723 1cd9e27f0fa16bd65edc431ca37bbcd5ad72b3bd
parent 601722 d95016c5fc991c075d10b4591491d50650a7c487
child 601724 4ef2bbae969ad672b10c01adcfc229855c071536
push id66200
push userhchang@mozilla.com
push dateThu, 29 Jun 2017 03:53:43 +0000
reviewersstandard8
bugs1351608
milestone56.0a1
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;