Use window.open but block use of window.opener
Asked Answered
D

6

60

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?

Dahl answered 14/11, 2016 at 16:37 Comment(0)
H
102

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.

Heavyladen answered 26/10, 2017 at 15:54 Comment(5)
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 featureHeavyladen
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.Skiff
@Skiff on what version of Chrome do you see that behavior?Heavyladen
I'm using version 62.0.3202.94Skiff
@Skiff 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. bugs.chromium.org/p/chromium/issues/detail?id=596068#c15Smalls
L
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/

Ladoga answered 14/11, 2016 at 16:44 Comment(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."Preparation
Mod note: do not introduce edits that are a commentary to the post.Sequela
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.Branum
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.Silicate
P
19

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". [...]

Papacy answered 25/3, 2021 at 13:50 Comment(2)
One small question - the documentation states use in the form name=value. So wouldn't it instead be 'noopner=<boolean>". Not sure if that should be true or false.Betthezel
@Betthezel you can see in the examples 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 valuePapacy
S
11

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

Staffman answered 2/10, 2018 at 9:35 Comment(0)
S
8

This worked for me:

const a = document.createElement("a")
a.href = args.url
a.target = "_blank"
a.rel = "noopener"
a.click()
Skiff answered 5/12, 2017 at 0:11 Comment(5)
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 thisDahl
I see. I thought you're goal was just the functionality.Skiff
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.Branum
This seems to be the most reliable method for cross browser support.Dispread
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.Silicate
S
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

Southworth answered 9/5, 2021 at 13:30 Comment(1)
This only has an effect on <a> elements. I tried this in Chrome 99 and I'm still able to access window.opener when windows are opened via window.open(url, "_blank")Mile

© 2022 - 2024 — McMap. All rights reserved.