58

A while back I ran across an interesting security hole

<a href="http://someurl.here" target="_blank">Link</a>

Looks innocuous enough, but there's a hole because, by default, the page that's being opened is allowing the opened page to call back into it via window.opener. There are some restrictions, being cross-domain, but there's still some mischief that can be done

window.opener.location = 'http://gotcha.badstuff';

Now, HTML has a workaround

<a href="http://someurl.here" target="_blank" rel="noopener noreferrer">Link</a>

That prevents the new window from having window.opener passed to it. That's fine and good for HTML, but what if you're using window.open?

<button type="button" onclick="window.open('http://someurl.here', '_blank');">
    Click Me
</button>

How would you block the use of window.opener being passed here?

Machavity
  • 30,841
  • 27
  • 92
  • 100

6 Answers6

96

The window.open() call now supports the feature "noopener".
So calling window.open('https://www.your.url','_blank','noopener') should open the new window/tab with a null window.opener.

I'm having trouble finding a reliable list of supporting browsers (and versions) - MDN states here that

This is supported in modern browsers including Chrome, and Firefox 52+.

From my experimentation, I see it works for:

  • Chrome 61
  • FireFox 56
  • Safari 11.1 (thanks Jiayi Hu for this)

But doesn't work for:

  • IE 11.608
  • Edge 40

(All tests on a PC running Windows 10...)

For backwards compatibility it may be better to combine this with t3__rry's answer.

G0BLiN
  • 905
  • 10
  • 18
  • If anybody tests this on additional browsers/OSs, feel free to comment or suggest an edit - it'll be nice to have a more complete picture of the support for this feature – G0BLiN Oct 29 '17 at 08:03
  • 4
    Wait, actually it does work -- but it doesn't open it in a tab. Its a new window with no frame. Pretty bizarre. Try it in your console. – Chet Dec 05 '17 at 00:05
  • @Chet on what version of Chrome do you see that behavior? – G0BLiN Dec 05 '17 at 04:35
  • I'm using version 62.0.3202.94 – Chet Dec 05 '17 at 16:07
  • 2
    @Chet As mentioned in the Chrome issue, you can do window.open(url,'_blank','toolbar=1,menubar=1,location=1,status=1,scrollbars=1,noopener') as a workaround to get it to open in a tab. https://bugs.chromium.org/p/chromium/issues/detail?id=596068#c15 – Chris Groh Feb 21 '19 at 16:41
34

Use

var yourWindow = window.open();
yourWindow.opener = null;
yourWindow.location = "http://someurl.here";

Credit goes to Mathias Bynens: https://mathiasbynens.github.io/rel-noopener/

t3__rry
  • 2,817
  • 2
  • 23
  • 38
  • 4
    As noted in the linked article, this method may trigger the pop-up blocker of the browser. I just tried the code, and indeed, yellow bar "Firefox prevented this site from opening a pop-up window." – Gras Double May 27 '18 at 17:57
  • 1
    Mod note: do not introduce edits that are a commentary to the post. –  Feb 03 '19 at 10:13
  • 1
    you still need to do this in Safari for the above to work properly: `Note that the JavaScript-based work-around fails in Safari. For Safari support, inject a hidden iframe that opens the new tab, and then immediately remove the iframe.` – hellatan Feb 26 '19 at 19:43
  • Works for me in Firefox but not in Chrome 86 where a popup is opened but the site isn't loaded. Chrome error message: `Uncaught DOMException: Failed to set the 'href' property on 'Location': The current window does not have permission to navigate the target frame to 'https://google.com'.` Reversing the last two lines work but not sure if it affects security. – Kenston Choi Nov 13 '20 at 04:39
18

Pointing out that it's a comma separated list of features (no whitespaces), so you could set 'noopener,noreferrer,resizable' i.e.:

window.open('http://sensible.url', '_blank', 'noopener,noreferrer,resizable')

From Mozilla docs:

windowFeatures Optional

A DOMString containing a comma-separated list of window features given with their corresponding values in the form "name=value". [...]

I.G. Pascual
  • 5,818
  • 5
  • 42
  • 58
  • One small question - the documentation states use in the form name=value. So wouldn't it instead be 'noopner=". Not sure if that should be true or false. – AshD Apr 21 '21 at 02:44
  • 1
    @AshD you can see in the [examples](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#toolbar_and_ui_parts_features) that toolbars and UI parts are key-value features, `status=yes, status=1, and status have identical results.`, but `noopener` and `noreferrer` are functional features so they exist or don't exist, but with no extra value – I.G. Pascual Apr 21 '21 at 14:14
10

According to the documentation (https://developer.mozilla.org/en/docs/Web/API/Window/open), in the following code

window.open('https://www.your.url','_blank','noopener')

The third argument contains the "WindowFeatures" (see https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Window_features) so it makes sense that it opens the target in a new window

Vincent Verrier
  • 221
  • 3
  • 5
7

This worked for me:

const a = document.createElement("a")
a.href = args.url
a.target = "_blank"
a.rel = "noopener"
a.click()
Chet
  • 18,421
  • 15
  • 69
  • 113
  • 3
    All you're doing is creating an anchor tag with JS DOM, which does the same thing as the HTML in the question. You're not using `window.open`, which is why I asked this – Machavity Dec 05 '17 at 04:24
  • 5
    I see. I thought you're goal was just the functionality. – Chet Dec 05 '17 at 16:07
  • 1
    this way works cross-browser and it is achieving the same functionality as using `window.open`. Both functionalities are ultimately using JavaScript whereas the question is purely surrounding HTML markup. – hellatan Feb 26 '19 at 19:44
  • This seems to be the most reliable method for cross browser support. – Daniel Congrove Dec 23 '19 at 14:45
  • But this may not return an object for you to check if the popup succeeded or not. This may be useful if your page is under a sandboxed iFrame that doesn't allow popups. – Kenston Choi Nov 12 '20 at 14:57
0

UPDATE: target="_blank" implying rel="noopener" behavior has been proposed in #4078 and fixed in PR#4330 on 31.01.2019

Most modern browsers have incorporated this change, but mostly those are the newest versions. Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#browser_compatibility

Daniel Danielecki
  • 8,508
  • 6
  • 68
  • 94