Rob--W / dont-track-me-google

Firefox and Chrome extensions to prevent Google from making links ugly.
MIT License
459 stars 26 forks source link

Invisible tracking on mouse down events #20

Closed Lekensteyn closed 6 years ago

Lekensteyn commented 6 years ago

For some reason Google searches still track you every time you have a mouse up event, it tries to access https://www.google.*/gen_204

Steps to reproduce:

  1. Open Firefox developer tools, Network tab
  2. Search for something
  3. Right-click on a search result to open a context menu/Ctrl-click (for Open in new tab)

Expected result: No new web request.

Actual result: Google is hungry for data.

Rob--W commented 6 years ago

There is no obvious way to stop this from happening, other than disabling navigator.sendBeacon. That's quite a big hammer, since it might also block legitimate functionality.

Since this "tracking" does not impact the usability of the links (i.e. the links are not ugly), I'm not going to add complicated logic to block these beacons (at best the logic is fragile and breaks within a few months, at worst it breaks functionality of Google sites).

Details from debugging:

  // This is an extract from Google's source code
  s_Rwa = function (a) { // Checks whether the event happened on an <A> element.
    if (a) {
      a = a.target || a.srcElement;
      for (var b = 5; 0 < b-- && a && 'A' != a.nodeName; ) a = a.parentNode;
      return !!(0 <= b && a)
    }
    return !1
  };
  s_do.prototype.Db = function (a) { // a is a model for the mouseup event
    // If the mouseup event happened on an <A>
    s_Rwa(a) && (this.log(new s_8n(a), !1, !0), s_5n(this, s_e(this.Ja, this, 'C'), 0))
    // The s_5n function calls some other functions and eventually schedules
    // an invocation of navigator.sendBeacon via setTimeout.
  };

I identified this code as follows:

  1. I reduced the document at google.com/search to a single link:
    document.body.innerHTML = '<a href="#">aaaaaaa</a>'
  2. I opened the network tab of the devtools, pressed the pointer on the link, and released the mouse button. Upon releasing the mouse button, I observed a network request attributed to beacon. From this I learned two things: 1) The request is likely generated by the mouseup event and the tracking request is sent via the navigator.sendBeacon API.
  3. Upon clicking inside the devtools another beacon request is sent, so I figured that Google also tracks the user when they unfocus the tab (i.e. in the "blur" event).
  4. When I click at the "js" icon next to the "beacon" label in the devtools, I see a stack trace, but it terminates at a non-event handler. I guessed that this must be an asynchronously scheduled task, likely with the setTimeout function.
  5. I monkey-patched setTimeout and after some trial and error to filter unrelated events, I came up with the following to get an unhibited call stack from the mouseup event up to the sendBeacon invocation:
    if(!window.sett) window.sett = setTimeout;
    setTimeout = function() {
     if (!arguments[1]) { // Google also schedules a task every 10ms, ignore it.
       console.log('setTimeout', arguments);
       arguments[0].apply(this, Array.from(argument).slice(2));
       return;
     }
     return sett.apply(this, arguments);
    };
    navigator.sendBeacon=function(){
     console.log('beacon with focus=' + document.hasFocus());
     if (document.hasFocus()) { // Ignore "blur" event, we only want "mouseup" event.
       debugger;
     }
    };
MariasStory commented 6 years ago

Hi @Rob--W, did you submit these changes?

Rob--W commented 6 years ago

Published as version 4.20.