Jan 27, 2011

Referrer Stripping

Inspired by Gabriel Weinberg's strange fixation on stripping search queries from HTTP referrers, I thought it would be interesting to describe how to actually strip referrers from an HTTP Request.  I don't think I've seen any good information on this elsewhere on the web.  It's a neat trick, albeit marginally useful.

First, let me explain what Gabriel is doing so as to compare.  If you do a query on Duck Duck Go and click a result, javascript on that page intercepts the click (in a sense) and sends you to http://duckduckgo.com/post.html instead.  http://duckduckgo.com/post.html is just static HTML with some more javascript that then re-sends you on your way to the actual destination page you had in mind, so the referrer sent to the destination is http://duckduckgo.com/post.html.  Duck Duck Go prefetches this URL before you click on any URL and your browser caches it, so there is only a tiny latency hit from running the javascript, and no network delay.  Reasonably clever.

This doesn't in fact strip referrers at all, it just changes them so that the referrer sent to the destination page is simply http://duckduckgo.com/post.html.  The query is gone, but the fact that you did a query and that you did so on Duck Duck Go isn't.  I'd honestly suspect the fact that one uses Duck Duck Go to be more revealing about demographics than the query itself, but I digress.

You as a user can strip referrers by modifying your browser: [Chrome, Firefox, Opera, IE?, Safari?]  What if you as a webmaster really want to strip the referrer for your users clicking on your links?  That's a browser feature and as a webmaster you can't change your users' settings, you can't, right?  Turns out that you can, but it's a pain in the ass because you need to do different things in different browsers.

With later versions of Webkit and hence Safari and Chrome, it's well known that attaching rel=noreferrer to an anchor will successfully tell the browser to not send the referrer on that request.  If you want to do this in javascript instead of through a plain anchor, you can make it happen by creating an anchor element in the DOM  and then simulating a click event via event.initMouseEvent.  Older versions of Safari and Chrome don't work here, and I don't know a workaround, but these browsers auto-update, so it's not common to see really old versions.

Firefox and IE don't support rel=noreferrer as far as I know.  However for as far back as I've tested them, a web page that performs a meta-refresh to a destination URL, even a 0-second refresh, will not send any referrer to that destination URL.  This doesn't work in Webkit - it passes a referrer, but for some reason it works in Firefox and IE.  It's undefined behavior, nowhere in the spec, so it could change in later versions of these browsers, buyer beware.  However rel=noreferrer is part of HTML5, so later versions of these browsers will probably eventually work with rel=noreferrer.  Want to do this with a plain link or javascript?  Simply stick an intermediate page with the meta refresh as an in-between URL like Gabriel does with javascript, and you'll have the same effect.

Konqueror and Opera don't allow any of these tricks last I checked (it's been awhile), and for your various other browsers (phones mostly), all bets are off.

I don't really know why you would want to strip referrers as a webmaster.  It literally is "breaking" the way browsers and the internet are supposed to work.  I've used it occasionally for internal systems (like a control panel) where you don't want a referrer to expose the existence of an URL not usually accessible, but one can use obfuscation with a different URL in this case, as Gabriel does.  Obfuscation is guaranteed to work in all browsers, and so is simpler to implement and maintain.

1 comment:

do said...

Looks like if the doctype is set as something like "HTML 4.01" then chrome will ignore the rel attribute, unless I'm doing something wrong. The full doctype of the one that was giving me trouble was
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">