Hacker News new | past | comments | ask | show | jobs | submit login
About rel=noopener (mathiasbynens.github.io)
411 points by dmnd on April 23, 2016 | hide | past | favorite | 109 comments



> Note that this also works when index.html and malicious.html are on different origins — window.opener.location is accessible across origins!

... Why. Why would anyone (not maliciously) consider this desirable behaviour?


Agreed. But what's more intriguing to me is that the proposed "solution" is to add yet another hack on top of that (rel=noopener), instead of doing something to fix the broken behavior of target=_blank.

I doubt that many sites rely on this broken behavior. And even if they do, browsers could still block it and show some warning to the user "Hey, this tab that just opened wants to change the URL of this other tab [allow, always, nope, never]", just like they do for popup windows or sites with broken SSL certs.

Does someone with more experience in these kind of issues know why it was decided to put the responsibility of fixing this on individual websites (rel=noopener) instead of browsers (blocking the URL changing or showing a warning)?


This common with OAuth flows. User clicks "login with x", a popup opens that redirects to an authorization page on x. The user then logs in on x, and gets redirected back to origin that takes the token in the hash fragment, and passes it back to the page the user is trying to login to, via window.opener.


Most of these use postMessage.


probably window.opener.postMessage. Though that doesn't excuse window.opener.location not being blocked in the name of the Same-Origin Policy...


"location" is not blocked cross-origin, because that allows you to navigate windows you opened, or subframes of yourself, even if they happen to not be same-origin with you at the moment. And it's been this way for over 20 years, and sites commonly depend on it. :(

So what you're suggesting is either some sort of asymmetric "same-origin" checks or .... something.


I don't really see the problem with making this asymmetrical. The security implications of a frame navigating its parent and a parent navigating its child frame seem very clearly different to my mind.

If you're suggesting it would be technically difficult, I'm extremely skeptical of that. The origin's relationship to the target frame should not be impossible to discern, and I'd be a little shocked if it isn't taken into account elsewhere.


The problem with making it asymmetrical is that in the case of two toplevel tabs (as opposed to frame and child) determining who's the "parent" and who's the "child" is a lot more complicated.

> If you're suggesting it would be technically difficult, I'm extremely skeptical of that.

I think it's technically difficult to establish parent/child relationships between toplevel windows, given opener disowning and so forth.

That's not even getting into the possible compat issues, of course, from the behavior change itself.


If that relationship weren't clear you wouldn't have a window.opener attribute to begin with.

That said, I'm also skeptical of legitimate uses for controlling the location of another top level window as well, so I'm fine with killing that option too.

Of course, I don't expect them to actually fix this, but I'm still waiting for a convincing argument that it should have been that way in the first place.


My point was that window.opener can be nulled out.

> I'm also skeptical of legitimate uses for controlling the location of another top level window as well

Happens all the time: open a popup, then navigate it to places. Not on web pages much nowadays, though it was more common in the past, but in various intranet apps? All the time.


I'm sure it can. That does not mean the browser needs to forget it. The parent/child relationship of browser windows is not some massive technological feat.

That something is used does not mean it is legitimate. I am not disputing that it is used. I am not saying I think they'll fix it. I am questioning the validity of the decision to allow it in the first place. I have no doubt that other means would be found to achieve the same end goals if it were not available.


> That something is used does not mean it is legitimate.

While I agree, in practice what this means is that either all browsers need to coordinate rollout precisely (and even then the result will be that many users just stay on insecure versions of browsers instead of updating) or you will have pages (or employers) telling users to switch to whatever browser lags in rolling this out.

We've seen this play out before. The result is that you end up with users picking whichever browser defects (which reduces the incentive for other browsers to do this) or being stuck on the equivalent of IE6.

The benefit of changes that do NOT break compat is that browsers can just roll them out without needing to worry about the above side-effects.


> I doubt that many sites rely on this broken behavior.

Any web based system where a pop up dialog is opened to allow the user to select something that is then inserted into the original page?


Good call! I guess i haven't seen any of those. But i've seen some internal web based systems that relied too heavily on popup windows and started breaking when tabbed browsing became a thing and brosers started blocking popup windows by default, so i don't doubt that there are probably systems out there relying on this weird behavior of target=_blank.

For those systems, though, i'd imagine most of them would have these popup windows on the same origin, right? So having browsers prevent child windows changing their parent's location if they are cross-origin seems like a sensible idea, or am i missing something else?


There are more than 1 billion websites. If just 0.1% of sites use target=_blank like that, you'd be breaking a million sites with your change. You can't use arguments like "I haven't seen any of those" or it "seems like a sensible idea" when making decisions like this.


The "I haven't seen any of those" was just as a comment on why i couldn't think of possible uses for this target=_blank behavior, not a justification for the proposed change (what a lame justification that would be! :)

That being said, i don't see how the proposal of browsers blocking popup windows from redirecting the parent window (if it's cross-origin) by default is any different from, for instance, them blocking popup windows from opening unless it was a user action that triggered them, which all browsers started doing by default quite some time ago. Could you elaborate on why this wouldn't be a sensible solution?


It does seem like a sensible solution, but the web isn't exactly a sensible place. People use terribly-written web sites for all sorts of things that are important to them in their life. Changes that potentially break these sites shouldn't be taken lightly.


Should the parent window be able to navigate the popup window, even if it's cross origin?

If not, now you're suggesting some sort of asymmetric security checks that depend on something that's not just the origins. Security checks that, chances are, will be easy to evade by malicious actors. At least I haven't thought of a non-evadable one here yet.


> you'd be breaking a million sites with your change.

Websites relying on such obscure misbehavior are already broken in my book. Fixing them would solve the problem better and cause fewer new problems for everyone else.


They aren't already broken for the people who rely on them.


It's a security risk, some sites relying on this will be affected by malicious content on sites they link to, so at the very least they'll now have to add one of the 2 limiting rel attributes on links that do not require the misbehavior to function.

Thanks to the bright and sensible handful of people who add extra cruft to HTML after a brief exchange on a mailing list 3 years after a problem was reported, the other 99.9% of the websites will have to be modified too.


Lots of websites used to use Java applets, but browsers decided they're not worth the security risk and made users jump through more and more hoops to start embedded Java.


For example Typo3 is using that, when you need to select something to be inserted/referenced into the current record. So any, Typo3 based website would break.


Probably there are, but they're hardly likely to rely on it working cross-origin, and if they are they almost deserve to have it broken...


Not sure but I would think anything that use a pop up to login using social media account would like to get an event back when successfully logged in?


Social media networks are well placed to get their little embedded code snippets updated across the web. And chances are, these links are being generated by a cross-origin javascript library anyway. If you wanted to be very generous, browsers could auto-whitelist origins of every javascript library loaded in the page.

In any remaining cases, there should still be some method to white-list the current behavior, e.g. rel=allowopener.


I suspect it's not a "why" but simply a "I didn't think to check for that" from the point of view of the person writing the browser.


Agreed. And while rel=noopener works in newer browsers (Chrome 49, Opera 36), I've previously found a need to patch this behavior across the board. Here's a little library I wrote: https://github.com/danielstjules/blankshield I also highlight the impact of "reverse tabnabbing" here: http://danielstjules.github.io/blankshield/


Here's my guess: some of Google's / Alphabet's nefarious practices include collecting information on users' previous pages. Fixing this bug the correct way (disabling window.opener by default when cross-origin) would put a dent on their cut, so they're using their leading browser to try and influence how the rest of the world tackles this issue: putting the burden on developers means 99.99% of websites will remain open to this bug and to their data collection.

Time to find Firefox's equivalent issue page and convince them not to follow the leader.


This is the new pop-under. Sites trying to serve as many ads as possible will open links with target=_blank and redirect the old window to an ad.


But doing what you describe doesn't rely on this window.opener security issue, right? Of course any site that can open popups can open popups and then also redirect somewhere else.

(Also, I'm not sure I've personally seen that)


So that's what's happening! With uBlock, all I see is a flicker on the browser's tab bar, and my history is gone. It's still annoyingly retarded.


I did try to provide a fix for the history-lost case for when a popunder is blocked, but in the end I had to give up because there was no way to make it work reliably (using current extensions API).

[1] https://github.com/gorhill/uBlock/issues/1028


Ha, no worries, I wouldn't have expected an ad blocker to know that for me, the dead tab and this new tab are semantically one. I'm just glad that the bad tab is dead. It's the ad that I was calling retarded :p

Awesome work btw, it runs like greased lightning in FF nightly.


Yeah. This is amazingly irritating.


Ths is a problem for Browsers, not developers. target=_blank is too embedded into the web.


developers can fix the problem for their users.


It's more expensive for a web dev to fix this than a browser to prevent it.


What is the correct way to force a link to open in a new tab, then?

Unfortunately "let the user decide" is not the best answer if you want to link to something like "terms and conditions" in the middle of a sign up flow or something. If the user doesn't know how to open it in a new tab on their own, this can be extremely frustrating I'd imagine.


> What is the correct way to force a link to open in a new tab, then?

What is the correct way to stalk, hunt, kill, stuff and mount the user?

Answer: there is no correct way to do something which is fundamentally incorrect.

> Unfortunately "let the user decide" is not the best answer if you want to link to something like "terms and conditions" in the middle of a sign up flow or something. If the user doesn't know how to open it in a new tab on their own, this can be extremely frustrating I'd imagine.

Abusing my browser is extremely frustrating for me. If I want to open a link (a link, see, not some horrid piece of JavaScript) in a different tab, I middle-click and get on with life. You don't need to do that for me, any more than you need to offer me a typing widget when I have a perfectly functional keyboard, or fake a link when I have a browser perfectly capable of understand the <a> tag, or check my (correct) email address with an incorrect regular expression.

Please don't break the Internet.


On the other hand, I almost never want to have a link open in the same tab. There's nothing more frustrating than being halfway down a page, forget to hold down ctrl when I click on a link, and have all of my state on the old page blown away and replaced with the new one.

Probably this is a result of the internet already being broken, since the worst of it is in infite-scrolling type things where my confidence that I can get back to where I was originally after going back is very, very low.


If you have a middle mouse button, you can middle click a link to open it in a new tab. Of course, that's if you didn't reprogram the middle button to do something else.


Reprogramming the meat behind the keyboard is often harder than reprogramming the machine.


With mice that don't have real middle buttons, trying to click the scroll-wheel without triggering a scroll event instead can be very trying...


Linking to stuff that you control is okay, because you know and control the contents inside the new window. So your example (terms and conditions created by you) is totally cool.

As described in the article, it is dangerous when the link's destination is not controlled by you. That destination has access to its opener's window and could potentially change the url to eg. a malicious look-alike of your site.

It's a consideration when linking to arbitrary pages, but when you own the destination (and trust that your site has no other security issues) then this becomes a non-issue.


This is one of the reasons why FB et al go to a special link before opening the actual target site.


That's more of a happy accident. Their primary reason is to track things.


I thought the primary reason was privacy: https://m.facebook.com/notes/facebook-engineering/protecting...


You can track click without a redirect.


Like using utm?


Like using javascript


>> If the user doesn't know how to open it in a new tab on their own, this can be extremely frustrating I'd imagine.

Is there any internet user who doesn't know how to open in new tab? Just curious to what type of users they would be.


Well I just had an "Oh sh*t" moment thinking about all the websites I built over the years at my old company that had target=_blank to commentors sites... Aw crap.

Not my problem anymore, but I never even considered this.


Maybe you could send them a note? Do you know anybody who's still working on the project?


It's a complicated situation. They owe me a bit of money and don't reply to any of my emails.


For future reference, IP transfer on final payment.


It's quite complicated really. I had been their lead developer, having worked my way up over a five year period with the company. My leaving was very cordial. I had been there a long time and they understood me wanting to grow. I started a project on the side for them almost immediately after I left because I knew they needed help.

I had a medical emergency (my tonsils swelled to the point where I could not breathe) and ended up needing surgery, so before the surgery I gave them the work that had been completed (By my estimate 80%) so they could finish the rest. They told me to get better and we would discuss how to handle the partial payment after my surgery.

While recovering, two of my former coworkers quit and took jobs at my current company. I had nothing to do with this. This is when my old company threatened to sue myself as well as them. Sigh. Our cooperate lawyer came back at them about them having no case and they soon dropped the whole thing.

I tried to pursue what I was owed, first emailing my contact and after receiving no response to a handful over several months beginning to loop in lower and lower managers I knew. I'm genuinely not sure if they had all been poisoned against me or if there was just some sort of email filter enacted, but I never heard a response from any of them.

Several years later they declared bankruptcy. I contacted their lawyer who informed me that only debts incurred within the last 6 months were perusable, and the money they owed me was not be perusable. Sigh. They are still in business now several years after the bankruptcy restructuring but on a skeleton crew. I don't believe I have any ability to pursue the money for the project now.

The whole ordeal was incredibly frustrating. It actually really saddens me as I LOVED that job and my coworkers there.


Sorry to hear you had a rough time at it. My original point still stands though. Transfer of code is fine, but if the contract stipulate that IP rights are transferred upon final payment then you have the copyright stick to wield in your fight for payment as they don't actually have a valid license for the software. Obviously I am not a lawyer and you should pay one to draft a generic contract you can use for contract work.


Can't you sue them then? Or at the least threaten to sue?


If you see my story which I commented on a different post in the hierarchy, it's VERY complicated.


Probably not worth it for a "bit of money"


Is there a practical reason that a reference to the opener window is given to the opened window? That seems like something we could do without.


Example: Google Slides where one tab has the presentation and another tab has the speaker notes. You want those to be in sync.


But presumably this example is not cross-domain. This behaviour should not be allowed by default for cross-domain links!


There are plenty of other ways to do this e.g. web sockets or localStorage.


Now, yes, but a lot of precedent was set before then. Even now both of the technologies you mentioned would add significant complexity – needing to start running an otherwise unnecessary WebSocket server, having to debug and workaround client bugs or network issues like large organizations blocking WebSockets.


This is a pretty old bug, I think I reported it a few years ago to Google.

EDIT: 2013 to be exact.


FYI, the article links to a Chromium issue from 2013:

https://bugs.chromium.org/p/chromium/issues/detail?id=168988

which links to another issue from 2012.

Edit: My purpose was to confirm the bug has been "known" for awhile, not to take away credit for you reporting the bug years ago. Congrats for independently discovering it before many people (such as myself) became aware of it.


Well there you go, although I submitted it trough a different channel.

For sure, I think its a very important bug that hasn't had much attention for years now, especially since so many websites use _blank, GMail being one of them.


I get that linking from a "trusted site" to a "not trusted site" is probably of greater concern. But, this `noopener` does nothing to address a similar attack demonstrated here: http://lcamtuf.coredump.cx/switch/.


If you open a page of your own site that then redirects to the target (like some pages do, presumably to hide the exact source URL in the referer-header before there was a header for it), is the opener-reference broken?


I'm using Chromium and even the link with `rel=noopener` seems to be able to "hax" the first page. Am I reading it wrong or is `rel=noopener` supposed to protect against this?


It's a bit confusing if you didn't pay close attention to the article, because neither link actually show the `rel=noopener` fix.

Instead, the two links present two different angles to the same problem. The first link demonstrates the attack using a page within the same domain (reasonable), and the second demonstrates that it will continue to work even when the link points to a page ordinarily restricted by cross-origin policies (potentially surprising).

If you manually add `rel=noopener` to either link, the attack won't work. Try it with DevTools.


Maybe the page changed? I see 3 links: non-Cross-Origin, Cross-Origin and noopener. The third one doesn't "hack" the page for me.


Same here on Firefox for iOS. Both links show the "hacked" text.


Note that all the opened page has control over is closing and changing the address of the tab. You can't insert HTML into the page, for example. Phishing seems to be the only problem this creates, but no more.


I built a quick userscript that treats rel="noopener" as default for links with target:"_blank".

It could be worth checking out if you want to avoid experiencing this security issue yourself (but I offer no warranties) or if you want to see if it would break any site you visit if browsers would enable the behavior by default.

https://github.com/jaredsohn/noopener_by_default


They ever heard of "security by default"? I guess no.


In the early to mid '90s, threat models on the web were quite a bit different from now.


I was implying "make it a default for everyone, now"


Right, but now you have 20 years worth of content which depends on the current behavior....


On this particular behavior unlikely


What makes you think this is unlikely? On the contrary, I think it's _very_ likely there are things depending on it. I don't expect there to be a huge number of them, but I also expect them to disproportionately be in things like intranet deployments where it's hard to even get measurements. :(


A link with _blank + expected to change/interact with opener? Maybe there's a few, but most cross domain transports would use window.open() manually.


Well, window.open() obviously has the same problem, with the same solution being proposed: the caller of window.open opts in to not allow the thing being opened to interact with it.

We could have different default behaviors for the two cases, of course: opt-in for links and opt-out for window.open.

But I still suspect that even just the link case is not as uncommon as one might wish. Happy to see data proving me wrong, though!


Security is hard, especially if your opponent is more clever than you. For example, the internet years later.


NoScript saves the day again.


Yeah, except breaking 99% of the modern Web.

NoScript has its place, for example in the Tor browser or in other high-security applications, but it's too much of a burden for everyday use.


> NoScript [is] too much of a burden for everyday use.

No it is not. It actually removes most of the burden from my daily browsing. Modern web is mostly a bunch of obstacles between the user and the information, and with NoScript (or xombrero in my case) the user skips over that. I believe most of the users don't care about layouts, transitions, syncing between tabs, etc, it's all designers' and marketers' caprice.


If your website breaks without Javascript, then it's the website's fault for not properly implementing progressive enhancement. Javascript is useful to enhance the page with better features, but the page itself should work without it.

If you tools/framework make this hard or generate output that incompatible with progressive enhancement, then I suggest you find (or write) better tools.


I do wonder for how many sites does this actually make sense to do. Take the number of users who use NoScript and are not willing to turn it off when the site doesn't work without JS, and then take the subset from those who would actually be willing to pay for using the website. [1] Do these niche users really generate enough revenue to pay for the toolchain & work culture changes necessary to have this progressive enhancement? What's more, this group of users doesn't even receive the charity boost that some other niche groups like the visually impaired might receive, that would lead to changes even without direct financial sense.

[1] Being NoScript users, they most likely also run some sort of ad blocker, so ad revenue from them is likely zero.


> makes sense to do

Do you use the pointer that fopen(3) returns without checking for NULL? Progressive enhancement is mainly error checking and handing failures gracefully.

> not willing to turn it off when the site doesn't work without JS

Why are you willing to make your business look shoddy and unprofessional? Running without javascript has always been an option, and always will be. Anyone that doesn't run the javascript obviously isn't expecting fancy features, but you should still show any text/images (or a basic form if that is relevant), probably along a suggestion that turning on javascript will probably improve their experience.

> changes necessary to have this progressive enhancement

That's the point - this shouldn't cost a lot, unless your tools are unusually braindead. Rails made progressive enhancement almost entirely transparent a long time ago. I believe there are several prerender-the-first-load plugins for several popular frameworks. If your tools aren't doing this for you (either automagically or otherwise), then those tools are missing important features.

> work culture changes

It is probably a good idea to pay any technical debt sooner, instead of tying even more projects to bad tools.

> users who use NoScript

NoScript users are NOT[1] the only group that will see your pages without Javascript. You don't control the client, which will always be unreliable.

Also, progressive enhancement isn't a boolean value; you should be checking for the availability of any feature you use. This may result in only partial support, which is probably better than no support (or a javascript error) if someone loads your page in an old browser or something unusual. The web is inherently a fluid environment, which makes defensive programming even more important.

> direct financial sense

What is the direct financial impact of showing people a broken website? Do you even analyze the server logs to find out how many people are impacted?

[1] http://kryogenix.org/code/browser/everyonehasjs.html


Some time ago I was surprised that my Google Search page was replaced by something else after I returned from some spammy page (opened in another tab).

As the browser I use, Opera 12, also treats all links manually opened in the new tab as if they had target="_blank", giving them opener access, I decided to remove the window.opener altogether by replacing the "opener" string with "opera" in the opera.dll. This way it gets overwritten by the normal window.opera variable and is essentially hidden. So far I haven't encountered a site legitimately relying on this behavior.


wouldn't a simple solution be <base rel="noopener">


In the right circumstances, which as far as I can tell are when crossing between security zones, Internet Explorer and Edge already seem to block this. I've never been able to pin down exactly what's happening, or to get Google login to work on our intranet sites with IE as a result.


There should be an option in content security policy to prevent this on all links.


sigh This is a perfect example of a title that should not have been changed. The original was objectively better than the current one. If you don't already know what rel=noopener is, you'd have no reason at all to click through on this. But the earlier title actually explained something about the content on the other end of the link.


HN submissions are kind of like startups. Often you have to break the rules to get off the ground. But once you have some lift, it's time to become boring and straighten out.


I have no idea what this submission is about. Why would I want rel=noopener?


The original title (and the point of the article) was about the security problems target=_blank has.

You want rel=noopener because the page it navigates to can't affect the content of the opening page.


It would be helpful if you stated what the original title actually was, especially now that you have the top-level post!


It was something like "TIL: target=_blank is harmful"


s/harmful/insecure/

IIRC.


Oh yeah, I think you're right. Anyway, it was something along those lines.


Does this "work" for cross origin requests? If I plant a `target=_blank` in my website, user clicks it, goes to my second website, do I have control over the website the link came from? If not, I don't see the security issue. Of course you can XSS yourself, what have you.


To some extent.. Yes.

The attacker can replace the current page with his own phising page.

Of course, the hostname part of the url would change, but the user is unlikely to notice that.


Case in point: People still fall for things like `facebook.com.totallynotaphishingsite.com'


It's a huge difference between clicking on a random facebook.com.totallynotphishing.com link, and being on the legitimate facebook.com and having that tab automatically go to a phishing site while you're not looking.


Yes, it says so lower down the article.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: