Hacker News new | past | comments | ask | show | jobs | submit login
Google Chrome to stop back-button hijacking (googlesource.com)
193 points by huntermeyer on Dec 18, 2018 | hide | past | favorite | 124 comments

I implemented the history.pushState API in Firefox many moons ago. Dunno why I didn't add this protection then, other than, it was a simpler time. It was around then that we added the API for vibrating a phone and we all sort of said "eh, someone could abuse this, but why would they?" (In my defense on that one I was on the side arguing that they would do it specifically for ads and we needed to lock it down.)

Anyway, I approve of this change.

Can you explain how this change stops abusers while still allowing front-end routing? I’m a bit confused because they seem mutually exclusive to me, or should I say they come together or not at all.

The commit comment explains, "Entries that are added to the back/forward list without the user's intention are marked to be skipped on subsequent back button invocations."

The commit doesn't include a mechanism for marking the should_skip_on_back_forward_ui flag, but the normal way Chrome verifies "user's intention" is waiting for a gesture/click in the page.

So if you're doing front-end routing in response to a user clicking on a link or button in your UI, or swiping the page or what have you, that will allow you to pushState and then intercept the back button, as you can today.

But if you attempt to pushState on load, that's not enough to establish intention; the back button will then skip your pushed states and leave the page.

A lot of seedier sites already abuse these mechanisms, by doing nasty things when you click to close a GDPR notification, focus a search box, or similar intention.

Browsers will probably never be clever enough to tell which clicks had "the right kind" of intention. The arms race continues!

Yeah but in that case the malicious website should only be allowed to push a single frame, allowing you to escape by going back twice.

This is much better then the current solution where you have to long-clicking the back button and manually pick a safe entry.

If I understood you correctly, if someone wanted to highjack my back history they could still do it on a random click? Is it only preventing non user interactive changes to the history or did I understand you wrong?

You are correct!

Is it possible for bad guys to just hijack on onmousemove? Or is that not sufficient?

Chrome keeps adding new QoL features and people will wonder why everybody uses Chrome.

"why would someone abuse this" shows an incredible naivete. Anything that can be abused will be abused.

The parent's non-specific "many moons ago" puts the date of such naivete long in the past, when Chrome was also adding a plethora of abusable APIs.

There was a kind of "if we don't expand the web platform, native apps from walled-garden app stores will take over" discourse at the time, from all browser implementors — less so from Apple, which could hedge its bets with the App Store.

One by one, the Chrome engineers continue to chip away at the techniques in The Annoying Site https://theannoyingsite.com (warning: open in a secondary browser).

Talk video here: https://www.youtube.com/watch?v=QFZ-pwErSl4 Source code here: https://theannoyingsite.com/index.js

Well done.

Wow, Firefox failed the chaos monkeyt test miserably! Felt like IE in 2001!

Don't open this site with 'reopen tabs after crash' option activated!! How can they even popup so much and how can the print dialog disable closing buttons??

Looking at the video, Chrome and Safari are in no way better off. Still, I thought popups were fixed 2008.

By the "choas monkey test" do you mean the annoying site in the parent comment? I'm using FireFox and it didn't do much for me. As I mentioned in another comment, I have set popups to appear in tabs, and that seems to mostly neuter the site.

It still managed to go full screen and play audio in the form of Nyein cat and some text to speech, which admittedly was annoying. But I managed to close the site and any "popup" tabs it made with two actions: Alt+F4 (I'm on Windows) followed by clicking "leave page". I had opened the site in its own window so my existing tabs were unaffected, but I wouldn't have been much worse off if I hadn't.

I believe Safari has an option to send all popups to tabs rather than new windows, so it is probably affected to a similar (low) level as FireFox. But I don't believe that Chrome has this option.

What is allowing site JS to physically move the browser window on my screen and how do I burn this feature with fire?

This only works in popup windows. According to the guy who made this website [1] this is to stop cross-origin communication, which is quite interesting. But it also has the effect that if you force popup windows to appear in tabs rather than windows then you do indeed burn the feature with fire. And IMO it's worth doing anyway, because no one has the right to open a browser window on my computer except me. It's possible in FireFox by changing browser.link.open_newwindow.restriction to 0 in about:config [2].

[1] https://youtu.be/QFZ-pwErSl4?t=558

[2] https://support.mozilla.org/en-US/questions/1066799

FireFox used to have an option to disallow pop ups to move themselves... I can't find that setting anymore, and I think Chrome used to as well, it still might. It's one of the first things I disable on my browsers due to some prank sites using this tactic for maximum trolling.

I wonder what could possibly be a use case why they would allow it and even built an API/interface for that.

The "dom.disable_window_move_resize" preference is still there. There doesn't seem to be UI for it, but it can certainly be set in about:config.

"how do I burn this feature with fire?"

What I do (for different reasons, but would still be effective) is to not allow Javascript to execute. Sites that are so poorly designed that they cannot operate without Javascript enabled are sites I simply don't use.

I shouldn't have done that. Though my downloads are now filled with cats which is nice :)

Jeez. probably could have done with a "don't open this in work" warning too...


This is worse than I thought.

Dear god. I didn't even know some of these things were possible to do via JS.

There was a cat and mouse game with adblockers and websockets a couple years ago, but I'm not sure how things work now.

Is anyone keeping an annotated list of annoyingsite techniques, to see what's still broken?

I'd love to gaze at the medusa, but indirectly if at all possible.

Opened it in chrome (my primary browser) in a new tab. It wasn't that bad to kill all the pop-ups from the task bar in windows. Took about a few minutes (<5). Rest of my open tabs remained unaffected.

Does anybody follows those "warning" advices?

I've recently noticed Chrome (71) on Mac is now hijacking the `Command + Q` shortcut and asking if I really want to quit. I appreciate people will occasionally shut down a Chrome session by mistake, but it seems a little ironic that they're clamping down on behaviour hijacking in one space whilst implementing it in another.

(Caveat: I'm not sure if this change is being committed by a Google Chrome dev or non-Google Chromium dev)

AFAIK, this has been the case for quite some time now. There is a menu option to disable this -

Chrome > Warn before quitting (cmd+q)

I've disabled cmd+q on my system, so I haven't run into this recently.

When using Command + W to close a tab, it's only a fat finger away to close the entire browser. Years ago that happened and it was a huge hassle since it wasn't easy to reopen all the tabs you had.

wasn't "reopen recent tabs" a launch-day feature for chrome?

I'm not sure. I remember hitting Command+Q a few times by mistake and losing whatever tabs I had open. Maybe I didn't know about that feature at that time.

I came here to say this. It should really be an opt-in behavior rather than opt-out.

It's not the only reason chrome has become a not-so-good citizen on macOS: the memory/CPU footprint is bad enough, but it also does things like give system-like popups when a new printer is detected on my network. I'm not sure when I permitted chrome to do this, and it seems like it's trying to subsume more and more of my system's function without asking. I find the command + q thing to be a particularly annoying version of this.

I miss being able to use backspace to go back.

I saw that too. There's a menu option to disable it.

Funny, one of the things that convinced me to switch away from chrome (back to Firefox) was when chrome got rid of the backspace-key-navigates-back. Sure, I could use an addon to restore the feature but .... why should I live with a browser that subverts decades of standard keyboard shortcuts?

It was a horrible keyboard shortcut that caused countless lost form entries. Just because something is standard doesn't mean it is good.

Google had several possible solutions:

- warn before navigating

- give options for the keyboard shortcut

- change shortcut unilaterally

They chose the third, which some (likely the overwhelming majority) preferred. I didn't, so I switched to Firefox. We're both happy this way I guess.

>warn before navigating

This requires too much page context. A search field being partially filled is very different than a long registration form being worked on.

>give options for the keyboard shortcut

You said yourself, they released an extension for this.

Seems like there should still be enough context. A user risks lost workflow if they've done nontrivial form entry. Exactly where you set that bar may be debatable or measurable, but certainly there is a difference between a partial search query and a full address form, for example.

Alternatively, the browser could just play it safe. I recall at one point the old Opera would prompt if unsaved form edits were present, on any navigation attempts (clicking away or browser back button/backspace). This saved me on many occasions and I never remember being annoyed by over-notification.

> You said yourself, they released an extension for this.

Oh was there an official one? At the time, the only extension I could find was some slightly-sketchy third party one that allowed you to set hot keys for many things.

> This requires too much page context. A search field being partially filled is very different than a long registration form being worked on.

Fair enough.

>Oh was there an official one?

Yes, Google released an official extension to coincide with the update that removed the hotkey.


I don't know when they did this, but Chrome also seems to remember form input when you back out, and re-fills the form if your reverse the backing out. That's a better solution than changing the shortcut because it works if you back out by other means, too, such as clicking the back button with the mouse or using the back gesture on a Magic Mouse.

Firefox does it to.

This has saved me many a time when I've accidentally done a back gesture on my Magic Mouse while composing an HN comment.

Sometimes, unless the flow is made of multiple pages of forms. Press back, you get to the previous form (with the fields now empty obviously), press forward, get a server 500 error.

In a nutshell, it feels like browser makers do their best to improve user experiences, and website designer do their best to ruin it again.

I'm gonna disagree with you on that. Numerous times have I filled a form only to press the back button by mistake.

Some websites just log you out if you press the back button.

Yeah, I'm not saying my opinion is popular. But having it as a flag, or offering a warn-before-navigating option would have kept me on Chrome longer. Anyway, I'm happily using firefox. So we both win!

Looks like you want an option, but not as an extension.


Perhaps you know this, but alt-left will go back as well. You can also install a vim extension and use capital H to go back.

I find not having the option really annoying when you're in a situation (e.g. relaxing) where you want to navigate with one hand. The right hand can drive the mouse and has easy access to pgup/down, arrows and backspace, but reaching for alt forces you to do crazy finger gymnastic, or use your second hand.

For me that's not the biggest Chrome deal-breaker anyway (besides privacy), as Chrome doesn't support stack-like behavior for switching tabs with ctrl-tab.

Not sure if there's a PC/Linux equivalent but Chrome (and other browsers I believe) on Mac also supports two finger swipe on the trackpad to go back/forward which works well in one-hand navigation flow.

(I also use BetterTouchTool to add similarly simple gestures for open-in-tab, close-tab, switch between tabs, and go-to-top/bottom)

Only the most anti-social sites break the back button, I kill the tab of any site that does.

What I hate and is much more common is the "do you want notifications". I'd love a "never ask about notifications again" option.

Any time I visit a non tech relative - their desktop is constantly popping up with messages they claim to know nothing about.

In the old days, you needed an RCE and some malware to do desktop popups. Now it's apparently just a feature. It's becoming an increasingly abused function.

The upside is, at least they don’t have a virus, not the kind that encrypts files or sends you CC info to China.

No, they just have the regular spyware conveniently bundled with almost every site they visit :).

Seriously, ad&tracking blocking is the first thing I do when I have to fix up a computer for a friend or family member.

This is why I applauded Firefox shipping it by default. It’s so much easier to leave it in than have to install something else or figure out which ad blockers are trustworthy.

I thought it was a great idea at first but in reality I only use it for the calendar and get annoyed by requests on every other site.

That's an option right in the settings. Along with all other permission requests.

Just set it to "never ask" or something similar and it will auto-deny all notification permission requests.

You can also enable it for specific sites if you want.

I didn't know, thanks.

For those trying to find it. It's settings -> advanced -> content settings -> notifications.

So you can turn off the top slider from "ask before sending" to blocked. Probably a good time to check your "allow" list on the same page. My blocked list is about 100 long.

There is a bit of hubris when it comes to websites even asking to allow notifications. No site is that important. why would I ever want to enable notifications under any circumstance ever. I generally get badgered about it by a site I'll probably only visit once.

It makes sense for web applications that are real applications. The CI suite my company uses sends notifications for a passed/broken build, which is a reasonable use. Mail sites can send new messages.

The problem is that there's lots of content the publisher thinks is notification worthy, but not the user. No, I don't need a notification every time you post to RandomNewsSite.com.

"The CI suite my company uses sends notifications for a passed/broken build, which is a reasonable use. Mail sites can send new messages."

That would still annoy the hell out of me.

This is basically why I don't read work email. If it's important, someone will come over to my desk asking if I got the email within 30 seconds. Hell I stopped listening to voicemail from a previous boss and just deleted it, For three years or so and it never caused a problem.

My default is now "select all, delete"

I just leave my email client and systems report open all the time. That way I can easily glance over and check if something needs my attention when I have some attention to spare, rather than be distracted by a notification appearing randomly over my work.

Especially considering support for desktop PWAs.

Google wants the web to stay on par with native apps, for obvious reasons.

That’s why they invest heavily in Chrome (and FF, to some degree), and work on all sorts of APIs like notifications, WebAudio, etc.

The decision process is probably not far off from “could a sandboxed, locally installed, native app do this?”

Turning notifications off by default would probably err to far on the other side. At the very least, they would want some noticeable UI indicator that notifications are available. I could also see it becoming a feature only available to sites after x visits/y days.

I want it for email and/or calendar. Maybe a few social media sites. That's it.

Yeah, it's useful for web.whatsapp.com, email, Slack. I appreciate that I can run these as browser tabs instead of having to explicitly install them as separate programs. The notification popup is useful for them.

It'd be interesting if browsers had a default setting that didn't allow a site to ask for notifications until you had switched to the tab and left it open a handful of times, or if they expired notifications automatically after you hadn't been to a site for a few days. It would also be interesting if they only allowed them for "pinned" tabs.

Speak for yourself. While I won’t allow that permission for most sites there are very legitimate exceptions, like a web based email client, or slack.

I was literally speaking for myself.

I definitely recommend doing this! UX-wise, I do wish that Chrome surfaced the option a bit better. Seems that a "never ask me again" checkbox, or even a shortcut to the relevant settings page, would be a nice touch.

Now I won't pretend to be within several magnitudes of the scale that Chrome runs at, but having given users the choice of "never ask for X again" in the past, it just ended up causing more issues than it ever solved.

People don't read dialogs, they just don't. And giving them the option of "never ask again for any site" would most likely mean that some would hit it and it wouldn't even register that it was something they did, let alone remember they did it for the rest of their time using that browser.

Then you start getting complaints about how Firefox has this notification feature but chrome doesn't, or notifications are broken on my chrome, or whatever else.

That's why I'm hopeful for some new browser APIs which will manage permissions across the board, and will use things like heuristics to allow or disallow asking for permissions based on things like amount of interaction, number of times they interact with the website, and the "kind" of site it is (a PWA should be allowed to ask for notifications fairly early on in the process of using it, a news website should have to wait until the user has come back at least a few times before being able to ask).

I don't envy browser vendors for having to make decisions on what is and isn't allowed there, because no matter what some well meaning sites will be caught in the crossfire, but it's by far the "least bad" solution in my opinion.

Thanks, just did it. The setting is here: Settings > Advanced > Privacy and Security > Content Settings > Notifications — Turn switch off

The lock icon in the address bar opens up site-specific settings, and has a link to open the full page for that domain. You can then hit the <- arrow and get settings for all sites.

In Firefox this option doesn't work. I have enabled block pop-ups with exception of a few internal work resources and I still see notification pop-ups on all sites.

Are you talking about a different issue? The parent posts dicussed notifications while your comment mentions popups, which are completely different things.

Notifications can be disabled as explained here: https://blog.mozilla.org/firefox/no-notifications/

Yes, that option was what I was talking about and it doesn't work on my work and home PCs.

PS: for example, quick screenshot from one news site with notifications: https://imgur.com/a/zWdJqMo

You've misunderstood settings. Blocking pop-ups don't have anything to do with notifications. They are completely unrelated functions.

I would love it if Google would identify sites that ask for notification permissions without any request from the user while crawling sites. Then just make a blacklist of those sites ala the safe browsing lists. There's no good usage for sites requesting notification permission without the user opting into it first.

I'm not sure about Chrome, but in Firefox I know I set the default permission to 'never' ask somewhere in about:config. The ideal life is one without unwanted notifications.

Is that dom.webnotifications.enabled? God I hope so, I don't know why I didn't look there sooner to turn off this crap.

Yeah that sounds about right. The other thing to disable is the full screen notification, which I think requires two keys now for some reason.

No need to drop to about:config... it's right there in the GUI for Privacy > Notifications -- a checkbox below the list of blacklisted sites.

On Firefox at least, you can: Preferences / Permissions / Notifications / [x] Block new requests asking to allow notifications

Even worse (and this is something that we also see on mobile): they usually implement a fake pop-up that asks for Location/Notification before showing the real one, just to be able to spam that fake pop-up while a dissent in the real one would hide forever


GMail breaks the back button in this way. There are intermediate "pages" in the app in some cases such that hitting the "back" button puts the browser in a state that causes a replay of the thing that brought the page from which you were clicking the "back" button. This happens a lot when searching through mail.

Once you're aware of it, it's simple enough to hold the back button and then go back several entries at once, but maybe this change will remove the "when I hit back, it goes back and then forward to where I was when I hit back" behavior in the first place.

>I kill the tab of any site that does

I believe this is one of the intended effects. For example, when you click on a link after a Google search, and then click the back button to go back to the search results, I imagine Google records this to downrank that page for that query in a small way. When you kill the tab, you forfeit this opportunity.

Firefox has this in about:preferences#privacy.

I don't use Chrome but FF lets you block requests to allow notifications. Its in settings>privacy&security>permissions.

Firefox has an option to disable notification prompts in about:config.

You will get more problems like these if the largest advertising company develops browsers. No excuse for the other browsers though...

The full page email popups/page dimming are the worst, I hate that it has caught on so much.

At least they have a nice big div to hit with your element blocker.

I know why Google has reacted now, I noticed few month ago that "clickfarm" websites began visually spoofing popular websites.

You accidentally click "clickfarm.com" from, say, google.com; then you press back button, it seems that you are "back," by the moment you click on another link, you realise that google.com page was fake, and is stuffed with invisible ads.

What purpose does invisible ads serve?

I think opacity set to 0, you didn't knew but you saw the ad and this will count as view?

Google looks for obscured ads, but there are new ways of tricking both the bot and the ads code coming out almost monthly.

What they look above all else are the organic clicks from clear IP ranges.

Please also fix the back button on the PDF reader built into Chrome; pressing the back button on my mouse seems to go nowhere.

I quit using chrome, but it would be nice if they alerted you to the fact that the site is hijacking the button. Personally, when sites do that, I immediately add them to a block list because they are shit and I don't want to visit them ever again. Now you'll never know.

How do you define "hijacking the button?" There are many valid uses of pushing state to history, and it's very difficult to distinguish a malicious use from a non-malicious use in the general case.

More in-depth discussion about the rationale and design process behind the intervention: https://github.com/WICG/interventions/issues/21

How does this work with single page apps where it's not uncommon to modify the history?

Sounds like it's only counting history entries in reaction to a user interaction, so if history is modified when the user clicks a link nothing will change.

I mean, aren't SPAs kind of a hijacking of how browsers are intended to be used?

I get what you're saying, but browsers haven't been stateless url-loaders since the late 90s. JavaScript in general, cookies, local storage, and plug-ins are all compromises with "pure" http navigation that (a) can be abused but (b) offer some much needed client-side cooperation in maintaining continuity and reducing repetitive traffic with the server.

There are ways of doing SPAs without polluting the history. In fact, I find them less frustrating to use. If your design relies on cues taken from malware pages, that's on you.

This is a frankly ignorant statement about SPA design. Pushing history on major navigation events has nothing to do with malware patterns. It is way of making SPAs compatible with user expectations and protocol investments based on the non-SPA web. It allows them to use their own tools for bookmarking, link sharing, and history management rather than forcing a from-scratch experience when they come to the sites.

Accessible navigation patterns are a key part of making the web accesible to decentralized improvement. If every SPA was a black box with its own navigation regime, the web would regress to walled garden apps that characterize 90s desktop and early iOS ecosystems.

I fail to see how I can be ignorant of what I find less frustrating and more compatible with my user expectations.

>It allows them to use their own tools for bookmarking, link sharing, and history management rather than forcing a from-scratch experience when they come to the sites.

Such as the behaviour of buttons outside the sandbox the browser provides? To quote you:

>browsers haven't been stateless url-loaders since the late 90s

Why break the expectations of the back button to hack the other tools to work how you'd expect when, really, all of the features you're describing worked perfectly fine before SPAs. The very reason pages like this frustrate me are because they don't work with the history management I expect.

The ignorant part was accusing SPA authors of copying malware patterns.

Regarding your opinion, I'm still not sure what you are comparing / suggesting.

Are you saying that late 90s reactivity on the web was good enough? I think you are very much in the minority on that one.

Are you saying SPA authors shouldn't expose URLs for different navigation paths to the browser? I think you would be surprised at all the places your browser experience breaks, like not being able to restore tabs, or copy links to interesting news stories.

The right way to do SPA is to design nav actions that feel like links, and only update the history in those. A user not watching carefully for page refreshes or net traffic shouldn't be able to tell the difference - and perhaps there are times this is happening on your browser that you aren't aware of because it can be done smoothly.

Hijacking history is a pattern used by malware and trying to stop it has broken some honest websites. This happened with Flash, with Java applets, with popups. It shouldn't be a surprise. As I see it, you're considering the malware an acceptable sacrifice for having SPAs work slightly better (for what you value as better and I don't).

Websites as apps will continue to work, they'll either lose this functionality or use normal links - the kind that are good enough for Facebook et al. Or for Hacker News.

>Are you saying SPA authors shouldn't expose URLs for different navigation paths to the browser? I think you would be surprised at all the places your browser experience breaks, like not being able to restore tabs, or copy links to interesting news stories.

No. All of these work with links. Aren't you trying to fit a SPA shaped piece in a website shaped hole?

Links force a reload of additional assets, break ongoing socket connections, and at minimum requires a re-rendering of the entire DOM, which is a waste for many navigation actions that still deserve their own URL. In particular, the many tcp handshakes necessary for a total page refreshes are expensive on mobile.

As a concrete exampke, rich news experiences that let you scroll through preloaded stories benefit a lot from not needing to re-render all of the surrounding layout when the content changes, and from assigning a different url to each story.

Btw, I never said this was worth the current trade-off with malicious sites, just that the history features were originally inspired and still used by honest sites. Fortunately we have better options than all or nothing; sounds like Chrome is implementing a heuristic that makes sure url history can only be updated in some proportion to human actions. Another option might be a whitelist check like "<site> would like to update your history".

Why do you think the history push API was introduced? For websites that work like SPAs.

That's not the full answer. It was introduced to accommodate people who wanted their pages to work like SPAs. It's the intentions of the people who are frustrating me.

I have the same concern.

Thanks - the mountain of JS on the other page failed on iOS

This is very much needed. Every site I visit through google news hijacks the back button. They only show their news letter signup page for the most part but still very annoying.

How about stopping right-click hijacking and smooth-scroll hijacking too?

Right-click is very useful in some cases. I have some productivity apps I have built for myself using web technologies, and it's extremely useful to be able to have custom context menus. Since web applications are doing more of the work that native apps used to, I'm ok with some level of annexation of the browser's UX territory when a site can really justify it.

That said, I would be in favor of an option to disable it globally, or for certain domains.

Right now you can't close a tab with ctrl+w if the "Would you like to see desktop notifications?" dialog is up. For a second I thought this was a fix for that.

Does this mean they no longer support history.pushState?

Will this affect SPA routers? How is "without the user's intention" defined, does it mean programmatically added items or something else?

If the current event loop task ( you may need to read up on the JS event loop ) was spawned by something like a click event then it is marked as a "user interaction". These tasks can do things like opening a popup window, start audio playback etc. whereas normal tasks are normally blocked from doing this.

It's a clever mechanism but malicious sites tend to just attach a click listener to the page and trigger everything when the user clicks for the first time.

On the other hand it can also be a pain to program around this if you need it. Say you have a webapp that allowed you render an image then display it in a popup. But the rendering is time consuming, so you do asynchronously in the background. The user clicks the button and you start the render. When the render is complete you try and open the popup, but your now in a different task where the popup is blocked. The best way to work around this is to display a modal dialog, saying that the render is complete. Then when the user hits "ok" you can use the task that the event created to display the popup. But it might confuse the user why they need to confirm the render is complete.

Couldn't you open the popup immediately while keeping a reference, do the proceeding, then just manipulate the reference to the window you just opened?

This is bad for my Electron app. I wish there would be a flag to disable all the web "security"(i.e isTrusted field requirements).

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