Firefox Lockdown

Discussion in 'privacy technology' started by guest, Sep 8, 2014.

  1. inka

    inka Registered Member

    Joined:
    Oct 21, 2009
    Posts:
    426
    TWB, using your test page, when I mark a given plugin "Never Activate"
    it is no longer detected by the "Plugins detected by enumeration:" section.
    The "MimeTypes detected by enumeration:" lists only the mimetypes mapped to the "EnabledPlugin.name" plugins... and revers mapping in "MimeTypes detected by checking 53 names:"

    For me, the result indicates that the browser is "leaking even less" than I expected.
    In preferences } Applications (iceweasel v31esr), brower has autodetected "xpdf" installed on the system and it is set as the default pdf handler... yet this isn't leaked (presence of the handler, ability to enumerate its name, nor the range of various mimetypes which are registerd to xpdf in the xdg mime database.

    If you are saying/worrying that a nebby script could embed a list of 3200 mimetypes and subtypes and poll to see (fingerprint? capitalize on a vulnerability)... I'm saying that the test results indicate that it would be able to glean a list of mimetypes which are registered to currently enabled PLUGINS. If your hardware-specific driver (or whatever) is not a PLUGIN, is just registered on your system as a mimetype handler, its presence (nor its associated mimetypes) is not leaked.
    I'm surprised noscript listens to DOMContentLoaded event. Foggy memory, I thought it was too late to intervene at that point (script parsing has already occurred). The "Mason" extension was one that I studied; IIRC, it intervened earlier than DOMContentLoaded.
    As you said, behavior may be different under windows. I tested in linux.
    To determine whether any "leakage" is occurring, I think you'll need to pare the number of enabled plugins and/or gather a definitive list of mimetypes registered to those. Only types outside that list would represent leakage, right?
     
    Last edited: Oct 14, 2015
  2. TheWindBringeth

    TheWindBringeth Registered Member

    Joined:
    Feb 29, 2012
    Posts:
    2,171
    Well, Applications reveals handler/application names (to the user). Whereas a navigator.mimeTypes['NonPluginAssociatedMimeType'] test seems to reveal (to content scripts) whether the browser thinks there is a handler for NonPluginAssociatedMimeType. I'm using NonPluginAssociatedMimeType here because that is what we need to focus on.

    The mimeTypesList built into my test page only checks for two PDF specific types: "application/pdf" and "application/vnd.adobe.pdfxml". Are those showing up in the "MimeTypes detected by checking names" table?
    These numbers are a bit off, but close enough for discussion purposes:

    Windows:
    MimeTypes detected by enumeration: 2 <-- Associated with plugins
    MimeTypes detected by checking 3215 names: 87 <-- 2 of these are associated with plugins

    Ubuntu LiveCD:
    MimeTypes detected by enumeration: 44 <-- Associated with plugins
    MimeTypes detected by checking 3215 names: 377 <-- 44 of these are associated with plugins

    IOW, virtually all of the results from testing navigator.mimeTypes[name] are not associated with plugins.
     
  3. inka

    inka Registered Member

    Joined:
    Oct 21, 2009
    Posts:
    426
    In my test results, "application/pdf" == nul, and "application/vnd.adobe.pdfxml" is entirely absent from the table.
    MimeTypes detected by enumeration: 50 (each maps to an emabled plugin)
    Plugins detected by checking 29 names: 1 (libflashplayer.so)

    I wouldn't have expected an Ubuntu system to differ significantly from my (debian-derived) antix15 in test results.
    I'm running fluxbox window manager here, no fullblown "desktop environment".
    Maybe the DE (thoroughness of its mime indexing) is the differentiator?
    Then again, I tested v31esr. Perhaps your newer (?) browser version performs more thorough sniffing.
     
  4. TheWindBringeth

    TheWindBringeth Registered Member

    Joined:
    Feb 29, 2012
    Posts:
    2,171
    That was an older version of Ubuntu. I just ran another set of tests, so might as well:
    Code:
    Firefox 41.0.1 + Flash Plugin on Windows 7...
      Plugins detected by enumeration:             1
      Plugins detected by checking 48 names:       1
      MimeTypes detected by enumeration:           2
      MimeTypes detected by checking 3416 names:  89
    
    Firefox 41.0.1 + Flash Plugin on Windows XP...
      Plugins detected by enumeration:             1
      Plugins detected by checking 48 names:       1
      MimeTypes detected by enumeration:           2
      MimeTypes detected by checking 3416 names:  97
    
    Firefox 37.0 + iTunes Application Detector Plugin on Ubuntu 15.04 LiveCD...
      Plugins detected by enumeration:             1
      Plugins detected by checking 48 names:       1
      MimeTypes detected by enumeration:           1
      MimeTypes detected by checking 3416 names: 669
    
    Oh, and: https://hackademix.net/2011/09/29/script-surrogates-quick-reference/
     
  5. TheWindBringeth

    TheWindBringeth Registered Member

    Joined:
    Feb 29, 2012
    Posts:
    2,171
    While reviewing the list of changes for 45.0.1, "Implement a PrefProvider for Remote New Tab Page" set off alarms and led me to:

    [Meta] Make about:newtab remote
    https://bugzilla.mozilla.org/show_bug.cgi?id=1176429

    I can't remember if I heard of Remote New Tab Page before. Anyway, it appears the intention is to move the about:newtab page to a remote server:

    newtab.cdn.mozilla.net aka dj2m5z2blkx8x.cloudfront.net.

    and grant that page/server special privileges so that it can bypass content isolation mechanisms and interact with internal browser components and private data. I didn't dig too deep, but it appeared to me that the existing NewTabURL.override() mechanism, which can be invoked via extension or autoconfig, remains. This reminded me of:

    give access to about:support data to specific whitelisted Mozilla websites
    https://bugzilla.mozilla.org/show_bug.cgi?id=1079563

    and "remote-troubleshooting" permissions granted to:

    input.mozilla.org
    support.mozilla.org

    Which also can be removed via extension or autoconfig. I don't recall those being accessible via the no longer supported about:permissions, but I'm too lazy to go back and check. There was also another bug or discussion, I can't remember where, about granting Mozilla servers the power to see actual user-agent information rather than the potentially overridden values that people setup. I don't know if they followed through on that.

    Point is: be aware that normal security/privacy protection mechanisms may not apply to Mozilla servers and perhaps partners.
     
    Last edited: Mar 29, 2016
  6. mirimir

    mirimir Registered Member

    Joined:
    Oct 1, 2011
    Posts:
    9,252
    That is mind boggling.
     
  7. JRViejo

    JRViejo Super Moderator

    Joined:
    Jul 9, 2008
    Posts:
    97,429
    Location:
    U.S.A.
  8. TheWindBringeth

    TheWindBringeth Registered Member

    Joined:
    Feb 29, 2012
    Posts:
    2,171
    Pref Exporter 0.6

    Used to export preferences from Gecko based applications (Firefox, Thunderbird, etc). Run this code via Scratchpad in browser context, Custom Buttons Addon, or other appropriate means. Export as TEXT and use a diff tool to compare files, or export as JSON and use my Pref Diff Tool to compare files.
    Code:
    (function() {
      let verInfoStr = "Pref Exporter 0.6"
      try
      {
        // Output format: either "TEXT" or "JSON"
        const format = "JSON";
    
        // Default basename (to which .txt or .json will be appended)
        const defaultBasename = "ExportedPrefs";
    
        // Use an application-specific prefix with default filename?
        const appSpecFilenamePrefix = true;
    
        // TEXT output only: Export a status field (locked, userset, default)?
        const exportStatusField = false;
    
        // TEXT output only: Export a type field (boolean, integer, string)?
        const exportTypeField = false;
    
        // TEXT output only: Separator between pref fields
        const sep = ";";
    
        // TEXT output only: End of line separator
        const eol  = "\r\n";
    
        // Nothing below here should need adjusting unless you are improving the code
        let prefBranch = Cc["@mozilla.org/preferences-service;1"]
                              .getService(Ci.nsIPrefService).getBranch('');
        let filename;
        if(appSpecFilenamePrefix)
        {
          let app;
          let appVersion;
          if(prefBranch.getPrefType("torbrowser.version") == prefBranch.PREF_STRING)
          {
            app = "TorBrowser";
            appVersion = prefBranch.getCharPref("torbrowser.version");
          }
          else
          {
            let appInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
            app = appInfo.name.replace(" ", "_");
            appVersion = appInfo.version;
          }
          filename = app + "_" + appVersion + "_" + defaultBasename;
        }
        else filename = defaultBasename;
    
        let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
        fp.init(window, "Pref Exporter output file", Ci.nsIFilePicker.modeSave);
        if(format == "JSON")
        {
          fp.defaultString = filename + ".json";
          fp.appendFilter("JSON", "*.json");
        }
        else
        {
          fp.defaultString = filename + ".txt";
          fp.appendFilters(Ci.nsIFilePicker.filterText);
        }
        fp.appendFilters(Ci.nsIFilePicker.filterAll);
        let rv = fp.show();
        if ((rv == Ci.nsIFilePicker.returnOK) || (rv == Ci.nsIFilePicker.returnReplace))
        {
          let invalidPrefTypes = 0;
          let unknownPrefTypes = 0;
          let prefList = [];
          let count = {value:0};
          let children = prefBranch.getChildList("",count);
          for(let i=0; i<count.value; i++)
          {
            let pref = {
                         name:   "",
                         status: "",
                         type:   "",
                         value:  "",
                       };
            pref.name = children[i];
            if(prefBranch.prefIsLocked(pref.name))
              pref.status = "locked";
            else if(prefBranch.prefHasUserValue(pref.name))
              pref.status = "userset";
            else pref.status = "default";
            switch(prefBranch.getPrefType(pref.name))
            {
              case prefBranch.PREF_BOOL:
                pref.type = "boolean";
                pref.value = prefBranch.getBoolPref(pref.name);
                break;
              case prefBranch.PREF_INT:
                pref.type = "integer";
                pref.value = prefBranch.getIntPref(pref.name);
                break;
              case prefBranch.PREF_STRING:
                pref.type = "string";
                pref.value = prefBranch.getComplexValue(pref.name, Ci.nsISupportsString).data;
                if((pref.status == "default") &&
                   (/^chrome:\/\/.+\/locale\/.+\.properties/.test(pref.value)))
                {
                  try
                  {
                    pref.value = prefBranch.getComplexValue(pref.name, Ci.nsIPrefLocalizedString).data;
                  }
                  catch(e)
                  {
                    // NOP
                  }
                }
                break;
              case prefBranch.PREF_INVALID:
                pref.type = "invalid";
                pref.value = "PrefTypeInvalid_ValueNotAvailable";
                invalidPrefsTypes++;
                break;
              default:
                pref.type = "unknown";
                pref.value = "PrefTypeUnknown_ValueNotAvailable";
                unknownPrefTypes++;
                break;
            }
            prefList.push(pref);
          }
          prefList.sort(function(a, b)
                        {
                          if(a.name < b.name)
                            return -1;
                          if(a.name > b.name)
                            return 1;
                          return 0;
                        });
          let output = "";
          if(format == "JSON")
          {
            let gcsdif = {};
            gcsdif.dif = "GCSDIF";
            gcsdif.version = "0.1";
            gcsdif.prefList = prefList;
            output += JSON.stringify(gcsdif);
          }
          else
          {
            for(let i=0; i<prefList.length; i++)
            {
              output += prefList[i].name;
              if(exportStatusField)
                output += sep + prefList[i].status;
              if(exportTypeField)
                output += sep + prefList[i].type;
              output += sep + prefList[i].value.toString() + eol;
            }
          }
          let foStream = Cc["@mozilla.org/network/file-output-stream;1"]
                                .createInstance(Ci.nsIFileOutputStream);
          foStream.init(fp.file, 0x02 | 0x08 | 0x20, parseInt("0666", 8), 0);
          let converter = Cc["@mozilla.org/intl/converter-output-stream;1"]
                                .createInstance(Ci.nsIConverterOutputStream);
          converter.init(foStream, "UTF-8", 0, 0);
          converter.writeString(output);
          converter.close();
          let resultMsg = "Exported " + prefList.length + " prefs.\n";
          if(invalidPrefTypes)
            resultMsg += "\nInvalid pref types: " + invalidPrefTypes;
          if(unknownPrefTypes)
            resultMsg += "\nUnknown pref types: " + unknownPrefTypes;
          resultMsg += "\nYour export may contain sensitive information.  " +
                       "Please protect the file appropriately.\n"
          let promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"]
                                .getService(Ci.nsIPromptService);
          promptSvc.alert(null, verInfoStr, resultMsg);
        }
      }
      catch(e)
      {
          let promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"]
                                .getService(Ci.nsIPromptService);
          promptSvc.alert(null, verInfoStr, e);
      }
    })();
    

    Pref Diff Tool 0.2

    Used to compare JSON export files created with Pref Exporter. Create an HTML file containing this code and load that in your browser. Then load the two JSON files you want to compare and Generate Results.
    Code:
    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Pref Diff Tool</title>
    <style type="text/css">
    body {font-family: "segoe ui"; font-size:12px;}
    table {width:99%;table-layout:fixed;}
    table, th, td {border-collapse:collapse; border:1px solid #999999;}
    table#footerTbl {border:none;}
    th {color:white; background-color:grey;}
    th, td {text-align:left; padding:2px; width:50%; word-wrap:break-word;}
    td {vertical-align:top;}
    td.label {color:white; background-color:grey; font-weight:bold; width:88px;
              word-wrap:normal;}
    td.expand {width:100%;}
    td.footerTd {border:none;}
    td#verInfoStr {text-align:right;}
    div.topgap {margin-top:6px;}
    div#helperDiv {display:none;}
    noscript {font-size:14px; font-weight:bold; color:red;}
    input.fileInput {width:90%;}
    span.prefName {font-weight:bold;}
    </style>
    <script type="text/javascript">
    
    const verInfoStr = "Pref Diff Tool 0.2";
    var resultsTable;
    var resultsFilter;
    var prefList1 = [];
    var prefList2 = [];
    var numMatchingRows = 0;
    var statusAvailable = false;
    
    function handleFileSelect(evt)
    {
      var id = this.id;
      var file = evt.target.files[0];
      var reader = new FileReader();
    
      reader.onerror = function(err) {
          alert("Error: " + err.toString());
        }
    
      reader.onload = function (evt) {
          var gcsdif;
          try
          {
            try
            {
              gcsdif = JSON.parse(evt.target.result);
            }
            catch(e)
            {
              throw("File is not a JSON file or it has been corrupted.\n" + e.toString());
            }
            if(gcsdif.dif != "GCSDIF")
              throw("File does not contain GCSDIF information.");
            if(gcsdif.version != "0.1")
              throw("GCSDIF version is not supported");
            if(gcsdif.prefList.length <= 0)
              throw("File contains no preference entries");
            if(id == "leftFile")
              prefList1 = gcsdif.prefList;
            else prefList2 = gcsdif.prefList;
          }
          catch(e)
          {
            alert("Error: " + e.toString());
          }
        };
    
      clearResults();
      reader.readAsText(file, 'UTF-8');
    }
    
    function generateResults()
    {
      var start = performance.now();
      clearResults();
      if((prefList1.length > 0) && (prefList2.length > 0))
      {
        var stats = {prefCountTotal  : 0,
                     prefCountLeft   : 0,
                     prefCountRight  : 0,
                     inBoth          : 0,
                     inBothIdentical : 0,
                     inBothDifferent : 0,
                     inLeftOnly      : 0,
                     inRightOnly     : 0,
                     different       : 0};
        var name;
        var prefNameObj = {};
        var prefList1Obj = {};
        var prefList2Obj = {};
        for(var i=0; i<prefList1.length; i++)
        {
          name = prefList1[i].name;
          prefNameObj[name] = 1;
          prefList1Obj[name] = prefList1[i];
        }
        stats.prefCountLeft = prefList1.length;
        for(var i=0; i<prefList2.length; i++)
        {
          name = prefList2[i].name;
          prefNameObj[name] = 1;
          prefList2Obj[name] = prefList2[i];
        }
        stats.prefCountRight = prefList2.length;
        var prefNames = [];
        for(var name in prefNameObj)
          prefNames.push(name);
        prefNames.sort(function(a, b) {
            a = a.toLowerCase();
            b = b.toLowerCase();
            if (a < b)
              return -1;
            if (a > b)
              return 1;
            return 0;
          });
        stats.prefCountTotal = prefNames.length;
    
        var helperDiv = document.getElementById("helperDiv");
        function HtmlEncode(s)
        {
          helperDiv.innerText = helperDiv.textContent = s;
          s = helperDiv.innerHTML;
          return s;
        }
    
        function insertRow(className, leftName, leftStr, rightName, rightStr)
        {
          var row = resultsTable.insertRow(-1);
          row.className = className;
          var cell0 = row.insertCell(0);
          var cell1 = row.insertCell(1);
          cell0.innerHTML = '<span class="prefName">' + leftName + "</span>" + HtmlEncode(leftStr);
          cell1.innerHTML = '<span class="prefName">' + rightName + "</span>" + HtmlEncode(rightStr);
        }
    
        var compareStatus = document.getElementById("compareStatusBox").checked;
        var compareType = document.getElementById("compareTypeBox").checked;
        var compareValue = document.getElementById("compareValueBox").checked;
        var outputStatus = document.getElementById("outputStatusBox").checked;
        var outputType = document.getElementById("outputTypeBox").checked;
        var outputValue = document.getElementById("outputValueBox").checked;
    
        const sep = ";";
        function getOutputStr(pref)
        {
          var str = "";
          if(outputStatus)
            str += sep + pref.status;
          if(outputType)
            str += sep + pref.type;
          if(outputValue)
            str += sep + pref.value;
          return str;
        }
    
        for(var i=0; i < prefNames.length; i++)
        {
          var name = prefNames[i];
          var left  = {pref:null, name:"", outputStr:""};
          var right = {pref:null, name:"", outputStr:""};
          var locationStr = "";
          if(prefList1Obj.hasOwnProperty(name))
          {
            left.pref = prefList1Obj[name];
            left.name = name;
            left.outputStr = getOutputStr(left.pref);
            locationStr = "InLeftOnly";
          }
          if(prefList2Obj.hasOwnProperty(name))
          {
            right.pref = prefList2Obj[name];
            right.name = name;
            right.outputStr = getOutputStr(right.pref);
            if(locationStr == "InLeftOnly")
              locationStr = "InBoth";
            else locationStr = "InRightOnly";
          }
          if(locationStr == "InLeftOnly")
            stats.inLeftOnly++;
          else if(locationStr == "InRightOnly")
            stats.inRightOnly++;
          else if(locationStr == "InBoth")
            stats.inBoth++;
    
          function isMatch(p1, p2)
          {
            if((p1 === null) || (p2 === null))
              return false;
            if(compareStatus)
            {
              if(p1.status !== p2.status)
                return false;
            }
            if(compareType)
            {
              if(p1.type !== p2.type)
                return false;
            }
            if(compareValue)
            {
              if(p1.value !== p2.value)
                return false;
            }
            return true;
          }
    
          var resultStr;
          if(isMatch(left.pref, right.pref))
          {
            resultStr = "Identical";
            stats.inBothIdentical++;
          }
          else
          {
            resultStr = "Different";
            if(locationStr == "InBoth")
              stats.inBothDifferent++;
            stats.different++;
          }
          var className = "All " + locationStr + " " + resultStr;
          insertRow(className, left.name, left.outputStr, right.name, right.outputStr);
        }
        statusAvailable = true;
        applyResultsFilter();
        var statsHTML = "PrefCountTotal: "  + stats.prefCountTotal + "<br />" +
                        "PrefCountLeft: "   + stats.prefCountLeft + "<br />" +
                        "PrefCountRight: "  + stats.prefCountRight + "<br />" +
                        "InBoth: "          + stats.inBoth + "<br />" +
                        "InBothIdentical: " + stats.inBothIdentical + "<br />" +
                        "InBothDifferent: " + stats.inBothDifferent + "<br />" +
                        "InLeftOnly: "      + stats.inLeftOnly + "<br />" +
                        "InRightOnly: "     + stats.inRightOnly + "<br />" +
                        "Different: "       + stats.different + "<br />";
        document.getElementById("stats").innerHTML = statsHTML;
      }
      else
      {
        alert("Error: No preference data from one or both files.  Were both selected and loaded OK?");
      }
      var end = performance.now();
      console.log("PrefDiffTool: generateResults() took " + (end - start) + " msecs");
    }
    
    function applyResultsFilter()
    {
      resultsFilter = document.querySelector('input[name = "resultsFilter"]:checked').id;
      resultsFilter = resultsFilter.replace("-Filter", "");
      resultsFilter = resultsFilter.replace("_", " ");
    
      numMatchingRows = 0;
      var row;
      // Leave first row alone
      for(var i=1; i<resultsTable.rows.length; i++)
      {
        row = resultsTable.rows[i];
        if(row.className.indexOf(resultsFilter) == -1)
        {
          row.style.display = 'None';
        }
        else
        {
          try
          {
            row.style.display = "table-row";
          }
          catch(e)
          {
            row.style.display = "block";
          }
          numMatchingRows++;
        }
      }
      updateStatus();
    }
    
    function updateStatus()
    {
      var numPrefs1 = statusAvailable ? prefList1.length.toString() : "TBD";
      var numPrefs2 = statusAvailable ? prefList2.length.toString() : "TBD";
      var numRows = statusAvailable ? numMatchingRows.toString() : "TBD";
      var cells = resultsTable.rows[0].cells;
      cells[0].innerHTML = "Prefs loaded from file: " + numPrefs1 + "<br />" +
                           "Result table rows matching compare and filter: " + numRows;
      cells[1].innerHTML = "Prefs loaded from file: " + numPrefs2 + "<br />" +
                           "Result table rows matching compare and filter: " + numRows;
    }
    
    function clearResults()
    {
      var rowCount = resultsTable.rows.length;
      // Leave first row alone
      for(var i=1; i<rowCount; i++)
        resultsTable.deleteRow(-1);
      document.getElementById("stats").innerHTML = "";
      statusAvailable = false;
      updateStatus();
    }
    
    function reset()
    {
      clearResults();
    
      // Variables
      prefList1 = [];
      prefList2 = [];
    
      // Compare
      document.getElementById("compareStatusBox").checked = false;
      document.getElementById("compareTypeBox").checked = true;
      document.getElementById("compareValueBox").checked = true;
    
      // Output
      document.getElementById("outputStatusBox").checked = false;
      document.getElementById("outputTypeBox").checked = false;
      document.getElementById("outputValueBox").checked = true;
    
      // Filter
      document.getElementById("All-Filter").checked = false;
      document.getElementById("InBoth-Filter").checked = false;
      document.getElementById("InBoth_Identical-Filter").checked = false;
      document.getElementById("InBoth_Different-Filter").checked = false;
      document.getElementById("InLeftOnly-Filter").checked = false;
      document.getElementById("InRightOnly-Filter").checked = false;
      document.getElementById("Different-Filter").checked = true;
      var resultsFilters = document.getElementsByClassName("resultsFilter");
      for(var i=0; i<resultsFilters.length; i++)
        resultsFilters[i].onclick = function() {applyResultsFilter();}
    
      // Files
      document.getElementById("filesForm").reset();
      var fileInputs = document.getElementsByClassName("fileInput");
      for(var i=0; i<fileInputs.length; i++)
        fileInputs[i].addEventListener('change', function(e){ handleFileSelect.call(this, e) }, false);
    }
    
    function init()
    {
      document.title = verInfoStr;
      document.getElementById("verInfoStr").innerHTML = verInfoStr;
      resultsTable = document.getElementById("resultsTable");
      if(!window.FileReader)
        alert('Required File APIs were not detected... this tool will not work.');
      reset();
    }
    </script>
    </head>
    <body onload="init();">
    <noscript>Error: This tool requires javascript</noscript>
    <div>
    <table>
    <tr>
      <td class="label">Compare:</td>
      <td class="expand">
       <input id="compareStatusBox" type="checkbox" /><label for="compareStatusBox">Status</label>
       <input id="compareTypeBox"   type="checkbox" /><label for="compareTypeBox">Type</label>
       <input id="compareValueBox"  type="checkbox" /><label for="compareValueBox">Value</label>
      </td>
    </tr>
    <tr>
      <td class="label">Output:</td>
      <td class="expand">
       <input id="outputStatusBox" type="checkbox" /><label for="outputStatusBox">Status</label>
       <input id="outputTypeBox"   type="checkbox" /><label for="outputTypeBox">Type</label>
       <input id="outputValueBox"  type="checkbox" /><label for="outputValueBox">Value</label>
      </td>
    </tr>
    <tr>
      <td class="label">Filter:</td>
      <td class="expand">
       <form>
        <input type="radio" name="resultsFilter" class="resultsFilter" id="All-Filter" />
        <label for="All-Filter">All</label>
        <input type="radio" name="resultsFilter" class="resultsFilter" id="InBoth-Filter" />
        <label for="InBoth-Filter">InBoth</label>
        <input type="radio" name="resultsFilter" class="resultsFilter" id="InBoth_Identical-Filter" >
        <label for="InBoth_Identical-Filter">InBothIdentical</label>
        <input type="radio" name="resultsFilter" class="resultsFilter" id="InBoth_Different-Filter" />
        <label for="InBoth_Different-Filter">InBothDifferent</label>
        <input type="radio" name="resultsFilter" class="resultsFilter" id="InLeftOnly-Filter" />
        <label for="InLeftOnly-Filter">InLeftOnly</label>
        <input type="radio" name="resultsFilter" class="resultsFilter" id="InRightOnly-Filter" />
        <label for="InRightOnly-Filter">InRightOnly</label>
        <input type="radio" name="resultsFilter" class="resultsFilter" id="Different-Filter" />
        <label for="Different-Filter">Different</label>
       </form>
      </td>
    </tr>
    <tr>
      <td class="label">Operations:</td>
      <td class="expand">
       <button onclick="generateResults();">Generate Results</button>
       <button onclick="reset();">Reset</button>
      </td>
    </tr>
    </table>
    </div>
    <div class="topgap">
    <form id="filesForm">
      <table id="files">
       <tr>
        <td><input id="leftFile"  class="fileInput" type="file" /></td>
        <td><input id="rightFile" class="fileInput" type="file" /></td>
       </tr>
      </table>
    </form>
    </div>
    <div class="topgap">
    <table id="resultsTable">
      <tr><th></th><th></th></tr>
    </table>
    </div>
    <div class="topgap">
    <table id="footerTbl">
      <tr>
       <td id="stats" class="footerTd"></td>
       <td id="verInfoStr" class="footerTd"></td>
      </tr>
    </table>
    </div>
    <div id="helperDiv"></div>
    </body>
    </html>
    
     
    Last edited: Apr 15, 2016
  9. TheWindBringeth

    TheWindBringeth Registered Member

    Joined:
    Feb 29, 2012
    Posts:
    2,171
  10. inka

    inka Registered Member

    Joined:
    Oct 21, 2009
    Posts:
    426
    If you allow tiles (er, page thumbs) on newtab page, ff loads each not-yet cached (or you've cleared the cache) url in a hidden window
    to create a thumbnail image for each tile, with all extensions bypassed/disabled.
    Although it ignores requests to set cookies when loading, it loads all 3rd-party assests (css, scripts, imagefiles, etc).

    I haven't found anything in the newtabpage and related code to indicate that header directives are treated differently.
    Ajax/xhttp requests during pageload are permitted; I haven't tracked down whether websocket connections are disallowed.
     
    Last edited: Apr 27, 2016
  11. mirimir

    mirimir Registered Member

    Joined:
    Oct 1, 2011
    Posts:
    9,252
    Any way to easily find out whether E10S will break particular add-ons?
     
  12. mirimir

    mirimir Registered Member

    Joined:
    Oct 1, 2011
    Posts:
    9,252
    Holy **** :eek:

    OK, so let's say that you're blocking WebGL in NoScript, using Canvas Blocker to prevent canvas fingerprinting, and blocking WebRTC with Disable WebRTC. So you're saying that Firefox loads visited pages with all that stuff allowed, just in order to generate a bloody thumbnail image?

    That is insane.
     
  13. hjlbx

    hjlbx Guest

    Is this confirmed ? If it is, indeed, the case then it is just plain stupidity.
     
  14. harsha_mic

    harsha_mic Registered Member

    Joined:
    Mar 11, 2009
    Posts:
    815
    Location:
    India
    I think these can be blocked either with uBlock Origin or uMatrix. Both are designed to see behind-the-scene requests too!
    For Example, i can see requests made by the browser for safe browsing lists update etc..
     
  15. TheWindBringeth

    TheWindBringeth Registered Member

    Joined:
    Feb 29, 2012
    Posts:
    2,171
    Could you please list the steps necessary to demonstrate this through a test? I ask because I just ran a quick one and the results seem to conflict with your conclusion:
    1. Installed FF46 portable app
    2. Installed latest ABP and removed all subscriptions including non-intrusive advertising exception.
    3. Typed address http://foo.example to load a test page which embeds third party content from bar.example. Confirmed third party content was visible in that tab.
    4. Hit the home button so that page was closed.
    5. Typed about:newtab to load the new tab page, confirmed the thumbnail for foo.example included images from bar.example, then pinned that tile.
    6. Added a ||bar.example^ ABP rule, so a future load of foo.example would not pull third party images from bar.example.
    7. Cleared recent history with all checkboxes checked.
    8. Closed browser
    9. Found the thumbnails folder, the thumbnail png for foo.example was still there. It would appear that clear recent history doesn't remove those. So I manually deleted the thumbnail png. Edit: Later I thought to also try changing the time range from its default to Everything, and that did delete the thumbnails.
    10. Launched browser again
    11. Looked at new tab page. The thumbnail for foo.example was regenerated and no longer contains images from bar.example. Checked server log, confirmed that images weren't requested from bar.example during this phase. It appears that ABP was able to block the requests generated by new tab page related thumbnailing.
    Theoretically, the behavior could be dependent on build, extension, request type, caching/order, etc. So I'm not trying to dispute the idea that there are issues in this area. If there are, it would be nice to have a reproducible test case.
     
    Last edited: Apr 28, 2016
  16. Alhaitham

    Alhaitham Registered Member

    Joined:
    May 18, 2013
    Posts:
    188
    Location:
    Egypt
  17. mirimir

    mirimir Registered Member

    Joined:
    Oct 1, 2011
    Posts:
    9,252
  18. deBoetie

    deBoetie Registered Member

    Joined:
    Aug 7, 2013
    Posts:
    1,832
    Location:
    UK
    Maybe I can provide a summary of my own:- use of "browsers" is a higher level of risk against anonymity than exchange of medium latency messages, where you have an agreed xml schema for those messages which can be parsed (and firewalled) by a relatively simple open source program executing locally, with no server-supplied code. How you view/construct those messages can be decoupled from the parsing/encoding aspect.

    Of course, one could say that a very simple html DOM parser is just that. Problem being that modern browsers are way beyond that in ways that risk privacy in very unpredictable and untestable ways.
     
  19. mirimir

    mirimir Registered Member

    Joined:
    Oct 1, 2011
    Posts:
    9,252
    What about text-mode browsers? Or even 'links2 -g'?
     
  20. harsha_mic

    harsha_mic Registered Member

    Joined:
    Mar 11, 2009
    Posts:
    815
    Location:
    India
    Yes there is at the linke.. :)
     
  21. deBoetie

    deBoetie Registered Member

    Joined:
    Aug 7, 2013
    Posts:
    1,832
    Location:
    UK
    Yep, they're a form of html dom parser with basic text rendering, that's OK. But if you still have expectations of interactivity in the return direction, you have the timing and profiling issues of any interactive session, because your user entry is "on" a remote mainframe (aka web server), with all the exposure that that implies.

    The problem with modern browsers is that they have become graphically rich dumb terminals on a mainframe, and offer the ability to execute scripts, provide various inbuilt services with access to your real machine and environment and so on. You emphatically do not fully control what goes to/from the server - hence the problems.
     
  22. TheWindBringeth

    TheWindBringeth Registered Member

    Joined:
    Feb 29, 2012
    Posts:
    2,171
    WRT to the compatibility shims:
    So those above numbers aren't great. I've stumbled across a few cases where the situation as listed there was incorrect/outdated. So maybe things are a bit better(?).

    It wouldn't hurt if we each reviewed the status for the specific extensions we think are important. Test extensions (in VM, portable app, or other non-critical environment), get the list updated if necessary, see if the developer is awake and working on full compatibility, etc. This is something we could do on our own schedule and without coordination.

    https://developer.mozilla.org/en-US/Add-ons/Working_with_multiprocess_Firefox
    https://wiki.mozilla.org/Electrolysis
     
    Last edited: Apr 28, 2016
  23. redcell

    redcell Registered Member

    Joined:
    Sep 27, 2010
    Posts:
    126
    I've tested my favorite add-ons (like CanvasBlocker, Random Agent Spoofer and Masking Agent) on Firefox Nightly. Most seem to work when it's updated. For example lower version of RAS is incompatible.
    I'm concern cause I also modified Firefox's configurations and wondering whether e10s will void any functionality.
    Has anyone really drill into the privacy implication using e10s?
     
  24. summerheat

    summerheat Registered Member

    Joined:
    May 16, 2015
    Posts:
    2,199
    Why and how should e10s worsen privacy?
     
  25. harsha_mic

    harsha_mic Registered Member

    Joined:
    Mar 11, 2009
    Posts:
    815
    Location:
    India
    Yes. Also, extensions working with the help of shims should also be considered as no go. It will degrade firefox performance.
     
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.