How do I get Sinatra to refrain from adding the X-Frame-Options header?
Asked Answered
W

6

35

I am using Sinatra to return some IFRAME contents, and I'd like to allow cross-domain src. Unfortunately, Sinatra is automatically adding an X-Frame-Options header to my response. How do I turn that off?

Weimaraner answered 20/10, 2011 at 18:43 Comment(0)
U
80

Sinatra uses Rack::Protection, in particular the frame_options option, which is what is setting the X-Frame-Options header.

You can configure which protections are used. Sinatra turns most of them on by default, (some are only enabled if you also are using sessions, and Rack::Protection itself doesn't enable some by default).

To prevent sending the X-Frame-Options header you need to disable frame_options like this:

set :protection, :except => :frame_options
Uranology answered 20/10, 2011 at 19:20 Comment(4)
That did the job, thanks! In my scouring of the internet, I'd run across all the individual pieces you mentioned, but hadn't been able to combine them into that one effective line of code that you gave me. Much appreciated.Weimaraner
Thanks a lot, @matt! I'm developing my first app in Sinatra, a Facebook canvas app, and this issue was consuming me for 2 days... :)Dreamland
This is a security risk If you only want to whitelist facebook, and not disable this important security feature at all, better do this: set :protection, :origin_whitelist => ['https://s-static.ak.facebook.com']Xanthochroism
@Xanthochroism that wouldn’t work (:origin_whitelist doesn’t effect frame_options). You could do something like :frame_options => "ALLOW-FROM https://s-static.ak.facebook.com", but the ALLOW-FROM value isn’t supported on Chrome or Safari. Longer term it may probably be better to use CSP. It looks like Rack-Protection will be getting support for CSP headers soonish.Uranology
M
5

Another solution, and the one I ended up with in production, involves monkey-patching Rack::Protection::FrameOptions:

# This monkeypatch is needed to ensure the X-Frame-Options header is
# never set by rack-protection.
module Rack
  module Protection
    class FrameOptions < Base
      def call(env)
        status, headers, body = @app.call(env)
        [status, headers, body]
      end
    end
  end
end
Mephitic answered 7/10, 2013 at 19:18 Comment(4)
I don't get why this is the only solution that worked, but it is!Restaurateur
I can't believe that you do actually use this in production. I believe that this acutally kills all security headers. You should provide an exception for the urls that you need insteadXanthochroism
In my case the whole app ran inside facebook's iframe, so it was appropriate. Also, the level of security this header provides is pretty minimal and wholly dependent on client support.Mephitic
@Xanthochroism the X-Frame headers could hardly be called security and in my testing at the time they were not supported very well by browsers when you were whitelisting URLs. It only seemed to work when they were either on (protect from all frames) or not present, as my solution above illustrates.Mephitic
M
3

Neither of the options presented here worked for my sinatra app. I ended up adding an after filter to modify the X-Frame-Options header to allow the app to be framed in by Facebook.

after do
  headers({ 'X-Frame-Options' => 'ALLOW-FROM apps.facebook.com' })
end
Mephitic answered 31/8, 2013 at 2:8 Comment(3)
I prefer this solution because: a) it works in sinatra 1.4.3 and b) it is more secure, I can put this statement directly within each individual action so that I can protect all but those I expect from all but those domains I expect.Dystopia
This ended up not working in every browser, so YMMV.Mephitic
As noted above, this is obsolete and should not be used anymore: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…Mcabee
C
3

I think I found a good way to handle this but would welcome feedback

The goal is to disable the X-Frame-Options just for one route to keep all the rack protection benefits:

    app.get'/hello_world' do
      headers({ 'X-Frame-Options' => '' })
      "HELLO WORLD"
    end

I believe this is a good option as it seems to prevent the rack protection from adding the SAMEORIGIN header on this one route

Conciliar answered 12/10, 2015 at 21:28 Comment(0)
B
2

The "set :protection, :except => :frame_options" answer did not work for me, using Sinatra-1.3.3

I had to hack a solution; I put this mutha in my config.ru file. Obvs you can change the header to be anything you want.

config.ru

class Rack::Protection::FrameOptions
  def header
    @header ||= {}
  end
end
Beeson answered 28/1, 2013 at 6:3 Comment(1)
This is generally a bad idea and extremely dangerous! Also might break your applicationXanthochroism
T
1

Actually, the solution given by @matt is still working with Sinatra v1.4.5.

Yes, Sinatra is using Rack::Protection and according to Configuring attack protection

you could either disable protection at all (which is not recommended):

disable :protection

or only disable frame_options:

set :protection, :except => :frame_options

Other than that, if your problem is not because of X-Frame-Options, it may be Access-Control-Allow-Origin, then what you have to do is to add below line to your route before the return statement:

response['Access-Control-Allow-Origin'] = 'http://www.example.com/'
Taxaceous answered 19/3, 2015 at 12:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.