Page MenuHomePhabricator

Remove outdated rel=noreferrer from target=_blank links created by $wgExternalLinkTarget
Open, Needs TriagePublic

Description

Context

NOTE: This is a draft of an essay I'll publish elsewhere. I know this overkill for the actual tiny change to MediaWiki core.

window.opener vulnerability

In 2016, the industry found a novel security vulnerability around links that open in a new tab by default. (This does not affect regular navigating from site A to B within the same tab, or when you choose yourself to open the link in a new tab. It is specifically about <a href=.. target="_blank"> and window.open().)

The newly opened tab has, by default, a way of communicating back to the original tab you came from, allowing the destination page to deceive you or otherwise alter the appearance of the previous tab via JavaScript. You can read more about this at https://mathiasbynens.github.io/rel-noopener/.

The collective response to this from the industry was to specify a new standard attribute called rel="noopener", which disables this JavaScript bridge. (If you're wondering why browsers don't change the default: It's backward-compatiblity with millions of websites and decades of Internet legacy.)

Additionally, it was realized that the pre-existing rel="noreferrer" feature, while seemingly unrelated, had the same behavioral side-effect in all major browsers of also disables this vulnerability.

Thus it became conventional wisdom to augment any and all "new tab by default" links (that is, links with target="_blank") and add the rel="noreferrer noopener attributes to them, where noreferrer helps older browsers, and noopener helps newer ones.

Referrer-Policy

Unrelated to all this, browsers have historically defaulted to sharing a complete URL via the Referer header when navigating between two pages. It used to be that if you were reading example.com/foo and went to elsewhere.org/bar, the latter could see you came there from example.com/foo. There were some exeptions (such as when using HTTPS and going to an unencrypted HTTP site), and individual sites and links could disable this via rel="noreferrer".

Since 2019 (or 2020, or 2021, depending on the browser) this default has changed. The default in all major browsers is now to only share the domain name of the site that referred your visit. This means elsewhere.org will know you came from example.com, but won't know what page you were reading. Or, in the case of Google Search, Slack, Gmail, Google Docs, etc won't know any of the identifiers or search keywords that may have been in the URL on the other end.

In line with the Extensible Web Manifesto, browsers did not merely change the default, but exposed a new mechanism to give site operators a choice: The Referrer-Policy header sets the default for an entire website (or set of web pages).

https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy
https://en.wikipedia.org/wiki/HTTP_referer

The collapse of traffic attribution across the open web

During the short span of time between browsers gaining the Referrer-Policy and changing its default, a number of security scanners started advertising Referrer-Policy as a "security" feature, which in turn led some security consultants to blanketly recommend Referrer-Policy: no-referrer for security reasons, without consideration the adverse impact (including us, in a minor way, through WordPress plugins, see T422587).

With every CMS, web platform, site framework, and individual sites that adopted either rel="noreferrer noopener after 2016 (to fix the window.opener vulnerability) or Referrer-Policy: no-referrer after 2017 (as part of routine security audits), the open web slowly erased itself from the perspective of referral data. While this might seem obvious and predictable in hindsight, I don't recall it being talked about at the time.

This is a textbook "tragedy of the commons" situation. Each site adopting this notices very little downside at first. It is only when sites around you do it as well, that it ends up draining your traffic analysis and traffic attribution, because you no longer know where anything comes from. It happens slowly enough and outside your direct control, that there is no obvious cause. It's just the trend that less and less traffic comes from a long tail of small and medium sites, and thus the proportion of traffic from major search engines and social media sites appears to get larger. Some of that is probably true, but it's hard to say much of that was a self-fulfulling prophecy (caused by this), or a coincidence that happen to unpack over the same decade.

The biggest players in tech on the web all depend on ad revenue, which requires people believe that Google, Facebook, Twitter, etc are worth paying for ad placement. One way that businesses decide whether and how much to spend, is referral data. This applies to explicit ad purchases, but also more subtly through decisions around whether to maintain an official social media presence.

Search engines such as Google rarely open links in new tabs by default, so they probably never faced any dilemma over whether and how long to keep rel="noreferrer noopener on their links, they simply didn't. They probably were also sufficiently informed and equiped enough to resist any "security advice" to deploy something like Referrer-Policy: no-referrer, as that would have been suicidal to their business. (I'm guessing they're not afraid of users not coming back, because it's a much more frequent but ephemeral experience. Plus, Google pays to be the default search engine, so people come back naturally. And the nature of web search is such that you're not likely to find the search result page useful once you've clicked on a result, unless you go back, which is a built-in feature.)

Social media giants like Facebook are a bit trickier, as their practice has been to serve feeds with posts where links open in a new tab by default, and leave the Facebook tab open in the background. This means posts have links with target="_blank" on them, making them vulnerable. Facebook implemented a novel workaround, akin to a two-stage rocket. They add rel="noreferrer noopener to all links which plugs the security vulnerability (and disables referrals). They then have a second phase that proxies external links through an intermediary redirect portal, e.g. https://l.facebook.com/l.php?u=https://example.org/foo&h=***. Once on that portal, referrals are working as normal again, and it redirects onwards, with the destination site able to see the traffic coming from l.facebook.com. (The reason for new-tabs-by-default on social sites is, I suspect, because, unlike search, social media companies probably found that people don't come back as much once they find something better to do, and benefit from an automatic return to "the feed" tab after users close other tabs. Or less cynically, it may be a better experience to not miss notifications from people messaging or mentioniong you, which on desktop historically depended on the tab staying open.)

Wikimedia Foundation wikis did adopt Referrer-Policy in MediaWiki in 2015 (T87276, T293109) but did not set it to the destructive no-referrer value. Instead, we set it to the origin-when-cross-origin value, which is the same as what modern browsers do by default, and improves privacy for readers with browser versions new enough to support <meta name=referrer"> (Chrome 2012, Firefox 2015, Safari 2018, per MDN) but old enough to not default to this value (Safari 2019, Chrome 2020, Firefox 2021, WHATWG Fetch spec change).

Breaking compatibility for target=_blank

In 2021, web standards revisited their decision to not change and break the default behavior of target=_blank new-tab links and changed the HTML spec. All hyperlinks now disable the window.opener feature by default, regardless of any "rel" attribute. It is now opt-in via rel=opener, instead of opt-out.

It was determined that real-world use of this legacy feature generally involves websites opening a new fixed-size popup window via window.open(), and rarely or never via <a href target=_blank>. The former still gets the window.opener mutation bridge by default, the latter does not.

This means not only is the "noreferrer" part redundant in rel="noreferrer noopener", the main rel=noopener part is is now redundant for security as well.

https://github.com/whatwg/html/issues/4078

There and back again

In 2017, WordPress added rel=noreferrer when saving new content that uses target=_blank (ticket 43187, ticket 37941, commit). In 2020, WordPress removed rel=noreferrer again (ticket, svn, git). But, I noticed that a number of recently written articles on WordPress blogs do still set rel=noreferrer on links. This is because the WordPress Gutenberg editor separately has the same bug (https://github.com/WordPress/gutenberg/issues/26914). I don't know yet why they decided to add the attributes there when WordPress does this already. But, after working on it for six years, they finally fixed and released this a few weeks ago in Gutenberg 33.0.0, which will hopefully be included in WordPress soon (WordPress/Gutenberg versions).

In 2023, a security scanner reported that soundlogo.wikimedia.org has no custom Referrer-Policy set. This was then set, and subsequently spread to wikimediafoundation.org and diff.wikimedia.org. This was reversed last week at my recommendation in T422587.

In 2016, MediaWiki added rel=noreferrer to new-tab links in Parser when $wgExternalLinkTarget is used (T133507). This did not affect Wikipedia, because this feature is not enabled in production. Nevertheless, we should remove this.

In 2025, Wikimedia Codex included rel=noreferrer as part of a newly developed "urlNewTab" option for the MenuItem component (T403791). We should remove this.

TODO

Audit: Codesearch noreferrer. Note that there do exist some legit uses of this attribute, such as in the ExternalGuidance extension, so don't blindly remove it.

  • Remove rel=noreferrer from the wgExternalLinkTarget feature in MediaWiki and Parsoid (not used in production).
  • Remove rel=noreferrer from the MenuItem component in Codex.

Event Timeline

SLopes-WMF edited projects, added: Parsoid (Tracking); removed: Parsoid.
SLopes-WMF moved this task from Tracking to Needs Triage on the Parsoid board.
SLopes-WMF edited projects, added: Parsoid; removed: Parsoid (Tracking).
SLopes-WMF moved this task from Needs Triage to Feature requests on the Parsoid board.
SLopes-WMF moved this task from Feature requests to Needs Triage on the Parsoid board.

Change #1297721 had a related patch set uploaded (by C. Scott Ananian; author: C. Scott Ananian):

[mediawiki/services/parsoid@master] Remove rel=noreferrer on external links

https://gerrit.wikimedia.org/r/1297721

Change #1297728 had a related patch set uploaded (by C. Scott Ananian; author: C. Scott Ananian):

[mediawiki/core@master] Remove rel=noreferrer on external links

https://gerrit.wikimedia.org/r/1297728

Change #1297744 had a related patch set uploaded (by C. Scott Ananian; author: C. Scott Ananian):

[mediawiki/extensions/ImageMap@master] Temporarily disable test involving $wgExternalLinkTarget

https://gerrit.wikimedia.org/r/1297744

Change #1297745 had a related patch set uploaded (by C. Scott Ananian; author: C. Scott Ananian):

[mediawiki/extensions/ImageMap@master] [tests] Remove rel=noreferrer on external links (update tests)

https://gerrit.wikimedia.org/r/1297745

Change #1297744 merged by jenkins-bot:

[mediawiki/extensions/ImageMap@master] Temporarily disable test involving $wgExternalLinkTarget

https://gerrit.wikimedia.org/r/1297744

Change #1297721 merged by jenkins-bot:

[mediawiki/services/parsoid@master] Remove rel=noreferrer and rel=noopener on external links

https://gerrit.wikimedia.org/r/1297721

Change #1297728 merged by jenkins-bot:

[mediawiki/core@master] Parser: Remove rel=noreferrer and rel=noopener on external links

https://gerrit.wikimedia.org/r/1297728

Change #1302203 had a related patch set uploaded (by Jgiannelos; author: Jgiannelos):

[mediawiki/vendor@master] Bump wikimedia/parsoid to 0.24.0-a9

https://gerrit.wikimedia.org/r/1302203

Change #1302203 merged by jenkins-bot:

[mediawiki/vendor@master] Bump wikimedia/parsoid to 0.24.0-a9

https://gerrit.wikimedia.org/r/1302203

Change #1297745 merged by jenkins-bot:

[mediawiki/extensions/ImageMap@master] [tests] Remove rel=noreferrer on external links (update tests)

https://gerrit.wikimedia.org/r/1297745