Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fixes Uncaught SecurityError when trying to replace history state with an URL from a different Origin #317

Closed
wants to merge 1 commit into from

2 participants

@jdurand

Chrome throws this error when using a redirect to point an image source to an external URL :
Uncaught SecurityError: A history state object with URL 'http://www.placecage.com/300/400' cannot be created in a document with origin 'http://localhost:3000'.

This skips the redirect URL history replace behaviour in these cases.

@reed
Collaborator

If the server is doing an external redirect, then the XDomainBlocker module should catch it and return a 403 status, causing Turbolinks to abort. So I'm not sure how you're seeing this error. Can you further explain the scenario?

@jdurand

At some point, I had an image tag like this: <img src="localhost:3000/placeholder/some_params">, my app then redirected to an external URL based on a bunch of stuff and I would get this error.

@reed
Collaborator

I'm still not seeing where Turbolinks factors into this. The browser handles the loading of image tags. Turbolinks only handles clicked links.

@jdurand

I can't remember how in hell I ended up doing something like this, but try it:

# routes.rb
get "/tltest" => "app/application#tltest", :as => :tltest

# application_controller.rb
def tltest
  redirect_to 'http://www.placecage.com/200/400'
end

# Some view.html.haml
= link_to image_tag(tltest_path), tltest_path

If you click on the image and then click back, you'll get the error I'm referring to. You won't get the error on my fork.
In this case it doesn't matter much, but I remember that it somehow broke whatever I was doing.
Turbolinks handles clicks and browser history. In this case the bug has to do with browser history management (tested on Chrome).

@reed
Collaborator

Why bother running the request through your app? Why not do this instead?

# routes.rb

# application_helper.rb (or wherever)
def tltest_path
  'http://www.placecage.com/200/400'
end

# Some view.html.haml
= link_to image_tag(tltest_path), tltest_path

The issue is on the server side, so that's where it should be fixed. I think I have a fix, but I need to do more testing to make sure it doesn't break anything. And I'm also still debating whether it actually needs to be fixed, given how unorthodox the practice that causes the issue to manifest is.

@jdurand

I agree, this is unorthodox. The example I gave was just to reproduce out the error. However, I think Turbolinks should handle requests the same way a regular request would be handled by the browser and not fail on this whether it's orthodox or not.

@reed reed closed this pull request from a commit
@reed reed Do not store redirect_to location in session if the request did not c…
…ome from Turbolinks - Closes #317
7baa5e9
@reed reed closed this in 7baa5e9
@reed
Collaborator

I believe I've fixed the root cause of the issue. Try it out and let me know how it goes.

@jdurand

Yes it works!
I found another JS Exception, but I think we'll have to live with it.

In the same use case, when clicking on the image Turbolinks will initiate an XHR and fail with 403 forbidden because the URL it's trying to fetch is on another domain. I looked around and couldn't find any solution to that. onreadystatechange never gets the 3xx response, so AFAIK there's no solution.

What do you think?

@reed
Collaborator

That's by design. It's what I described in my first response. Javascript doesn't throw an exception; the request returns an error status and Turbolinks handles it client-side by doing a full request. The behavior is a safeguard against XSS, so it should stay as it is.

@jdurand

It's all good then!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 24, 2013
  1. Fixes Browser Uncaught SecurityError

    Jim authored
This page is out of date. Refresh to see the latest.
Showing with 3 additions and 1 deletion.
  1. +3 −1 lib/assets/javascripts/turbolinks.js.coffee
View
4 lib/assets/javascripts/turbolinks.js.coffee
@@ -97,7 +97,9 @@ reflectNewUrl = (url) ->
reflectRedirectedUrl = ->
if location = xhr.getResponseHeader 'X-XHR-Redirected-To'
preservedHash = if removeHash(location) is location then document.location.hash else ''
- window.history.replaceState currentState, '', location + preservedHash
+ host = new RegExp(window.location.host)
+ if location.match(host)
+ window.history.replaceState currentState, '', location + preservedHash
rememberReferer = ->
referer = document.location.href
Something went wrong with that request. Please try again.