Remove :js responder

I much appreciate RoR, its community Homakov included. I never saw RoR security team at least one time to appreciate Homakov’s findings. Perhaps you should take it closer by first recognize his security work over RoR. I’m quite sure that Homakov would have comply to your rules in the end.

I am trying to imagine “dynamically generated public JavaScript” but nothing comes to my mind. Any small bit of information, even the fact that user is logged in, or blocked, is somewhat sensitive IMO. Opt-out is must-have indeed. E.g. in development env it might be convenient to reach .json endpoints directly.

I am trying to imagine "dynamically generated public JavaScript" but

nothing comes to my mind.

This is an old trick.

Your service provides a small JavaScript snippet for hosting sites to embed. The snippet generates a SCRIPT tag in the hosting DOM whose creation triggers a (GET) request to fetch JavaScript from the central service, in the provider's domain. That as you know is not subjected to the same-origin policy, hence the technique.

See for example the snippet of Disqus:

    Disqus | Install instructions for Universal Code

The response contains JavaScript, whose evaluation injects content in the host page.

The user browsing the hosting website is not a user of the service provider, users may not even realize there is a centralized service providing that section of the page.

Embeddable gists are another example:

I’ve been using RJS for quite a while and I think it’s a wonderful way to render server-side template and form errors. I agree with everyone that this issue is important as my ticket shows (Ajax request doesn't validate CSRF token if the request is GET · Issue #11509 · rails/rails · GitHub).

I’ve had a somewhat crazy idea a few months back and I’m sorry if I side track the issue at hand. I am currently thinking about using a websocket for this kind of query (I have a very rough alpha working). The gist would be to have a websocket open on DOMContentReady (there wouldn’t be any reconnection due to the nature of turbolinks). From there, every ajax request would be made through the websocket instead of the normal HTTP procedure. This, as far as I understand, would have the advantage of making XSS impossible (Websockets follows the same-origin policy).

Right now, this idea would be somewhat of a hack for different reason: A Javascript client script would have to take every click event on a[data-remote=true] and take the URL and pass it to the websocket which would then use Journey as normal to dispatch the request to the right controller. The response would then be sent through the websocket (The headers could be entirely drop).

I think this idea could possibly fix this issue altogether while being completely transparent to developers.

Do I make sense? Is it a stupid idea?

Marius, your solution is not much different from responding a render :json : you send only the data, and the processing code is already on client side; transponder.js seems to me that it adds an abstraction level in order to manage the data, but it is different from RJS, which sends the execution code too, that is necessary for running the examples made before, like Disqus, or single page apps.

transponder.js a good solution if you don’t want / need to send the execution code, as render :json , but I think I got that RJS is necessary for other contexts.

Sorry, I meant Zack.

so if/when this will make it to master?

Jeremy Kemper is assigned to this. We will get this in shortly.

Just had a flash about this issue.

JSON has a similar issue and it solved it by prepending ‘for (;;);’ before the JSON payload.

Wouldn’t it be an idea to prepend any js.erb template with ‘for (;;);’ and use String.substr(9) (9 being the size of the for loop) to remove that loop before injecting the payload in the . This way, JS would be safe without need to do extra verification on the server side.

that solution is ugly. for(;:wink: means code on server side to add it and code on client side to slice. While .xhr? check is one line in ApplicationController.

For Rails 4.1: CSRF protection from cross-origin <script> tags by jeremy · Pull Request #13345 · rails/rails · GitHub

Since we don't know the response format until rendering, it's simplest to use an after_action to verify that we aren't serving JS to a non-XHR GET request.

This piggybacks on the same `protect_from_forgery` declarations that apps already use, so they'll transparently get protection without changing anything.

Apps that intentionally expose JavaScript responses (like third-party widgets, per-customer API embeds, etc) will need to exclude those actions using existing `protect_from_forgery` API.

Thanks everyone for the (long) discussion and thanks to Egor for the initial report - months ago now! - and this reminder.