The window.opener Security Vulnerability and Using the rel=noopener Tag

Recently I updated my site's code to add the rel=noopener tag to friendly links and external links, so today let's discuss why we use the rel=noopener tag. In fact, this is a security vulnerability — JavaScript provides window.opener to get the Window object that created the window, and that's where the problem begins. Let's take it step by step.

Recently I updated my site’s code to add the rel=noopener tag to friendly links and external links, so today let’s discuss why we use the rel=noopener tag. In fact, this is a security vulnerability — JavaScript provides window.opener to get the Window object that created the window, and that’s where the problem begins. Let’s take it step by step.

About window.opener

The window.opener property is a readable and writable property that returns a reference to the Window object that created this window. For example, window.opener.close() would close the source (parent) window. But an link only has this problem when it has target=“_blank”.

Discussing the Security Risk of window.opener

We know we can obtain the Window object that created the window via window.opener, so there’s quite a lot that can be done. The security of web applications is largely guaranteed by the Same Origin Policy (SOP). But when a child page accesses some properties and methods of window.opener.location, it is not protected by SOP — that is the core of the vulnerability.

Example: suppose the parent page has a link that opens a child page in a new window:

<a href="https://www.renfei.net/demo.html" target="_blank">demo</a>

In https://www.renfei.net/demo.html there is this snippet:

<script>
    window.opener.location = 'https://www.google.com/posts';
    //window.opener.location.replace('https://www.google.com/posts');
</script>

In most browsers, after opening the child page via a link in the parent page, the child page can use window.opener.location to redirect the parent page away (both JS lines above can redirect; the difference is that replace produces no history entry).

If a user-submitted link or a friendly-link site is hacked, and the redirected child page contains such code, it can control the parent page — and it works even across different domains, e.g., redirecting to a phishing page or a malicious drive-by download page. This phenomenon was discovered long ago and exploited in black-hat SEO.

The rel=noopener Tag

To fix the security vulnerability caused by window.opener, a new attribute was introduced: rel=noopener — ensure new browsing contexts are opened without a useful window.opener. When you add this attribute to an link, the newly opened page can no longer obtain the parent page via window.opener, while the Referer is unaffected. This effectively prevents phishing redirection attacks where a child page controls the parent page, and stops spammers from hijacking your web page.