Testing CSRF protection in Rails

Ever wanted to test your CSRF protection in a Rails app? For example, in a situation when you have a custom “remember me” cookie set and you need to overwrite Rails’ handle_unverified_request to clear it so it does not open a big security hole in your app? I know I did and it took me a while to find out how to do that, so I figured it would be good to write about it.

Here’s how to do it (in Test::Unit, but it’s the same for RSpec):

setup do                                                           
  # Enable CSRF protection in this test                            
  ActionController::Base.allow_forgery_protection = true           
end                                                                
                                                                   
teardown do                                                        
  # Disable CSRF protection for all other tests                    
  ActionController::Base.allow_forgery_protection = false          
end

Adding the above will make it so that the authenticity_token is added to each generated <form> element and will be required to be sent with each non GET request.

Painful ruby 1.9.2-p180 to 1.9.2-p290 upgrade

I did the recommended upgrade of my current p180 to the new p290 using rvm:

$ rvm upgrade ruby-1.9.2-p180 ruby-1.9.2-p290

First annoyance – moving gems from one gemset to the new one took over 40 minutes. Have really no idea why.

But after it was done, whenever I tried to run ‘gem’ or ‘rake’ or ‘bundle’ I got:

Invalid gemspec in [/home/jkl/.rvm/gems/ruby-1.9.2-p290/specifications/guard-0.8.1.gemspec]: invalid date format in specification: "2011-09-29 
00:00:00.000000000Z"
Invalid gemspec in [/home/jkl/.rvm/gems/ruby-1.9.2-p290/specifications/json-1.6.1.gemspec]: invalid date format in specification: "2011-09-18 0
0:00:00.000000000Z"
Invalid gemspec in [/home/jkl/.rvm/gems/ruby-1.9.2-p290/specifications/heroku-2.8.4.gemspec]: invalid date format in specification: "2011-09-23
 00:00:00.000000000Z"
Invalid gemspec in [/home/jkl/.rvm/gems/ruby-1.9.2-p290/specifications/guard-0.8.4.gemspec]: invalid date format in specification: "2011-10-03 
00:00:00.000000000Z"
Invalid gemspec in [/home/jkl/.rvm/gems/ruby-1.9.2-p290/specifications/multi_xml-0.4.0.gemspec]: invalid date format in specification: "2011-09
-06 00:00:00.000000000Z"
Invalid gemspec in [/home/jkl/.rvm/gems/ruby-1.9.2-p290/specifications/heroku-2.8.1.gemspec]: invalid date format in specification: "2011-09-21
 00:00:00.000000000Z"
Invalid gemspec in [/home/jkl/.rvm/gems/ruby-1.9.2-p290/specifications/metrical-0.0.7.gemspec]: invalid date format in specification: "2011-09-
11 00:00:00.000000000Z"
...
and so on...

The above is another manifestation of the YAML engine switch from Syck to Psych and all of the incompatibilities it has brought. The problem is that now you have to reinstall all of your gems, because all installed gems have wrong gemspec specification. D’oh.

I fixed it by running:

$ rvm gemset empty

And then bundling in each project…

$ bundle

Some more reading material.

Bug of the day

Completely bad code follows, beware.

Silent error in Ruby 1.8.7:

x = [:a, :b]
=> [:a, :b]

x.slice!(:a)
=> nil

x
=> [:a, :b]

Explicit error (resulting in a failing test) in Ruby 1.9.2:

x = [:a, :b]
=> [:a, :b]

x.slice!(:a)
TypeError: can't convert Symbol into Integer

Just yet another incompatibility, but for the better!

Run guard-jasmine-headless-webkit without X server

You write specs for your javascript, right? If not, you really should.

jasmine-headless-webkit really helps with that. guard-jasmine-headless-webkit makes it all even more enjoyable, although there’s one caveat – it’s not so easy to set it all up.

There is a great guide for that, but it lacks some important details on running guard-jasmine-headless-webkit without graphical interface (X server).

Assuming you already have Xvfb installed, execute this command to run Xvfb in the background:

Xvfb :0 -screen 0 1024x768x24 > /dev/null 2>&1 &

And then you need to setup the DISPLAY shell variable in order for guard-jasmine-headless-webkit to automatically connect to our virtual frame buffer. Here’s the excerpt from my .bash_profile (it first checks if there is Xvfb running on display :0 and only then sets the DISPLAY variable):

xdpyinfo -display :0 &>/dev/null && export DISPLAY=:0

Hash to HTML (hash2html) in Ruby

I needed to output a Hash as a nested HTML structure. Googling didn’t find any satisfactory results, so I decided to roll my own. UL/LI tags seemed like the best choice. It was a nice exercise in recursion.

The result is a function, which outputs a nicely indented HTML. Note, however, that it’s a very basic solution. It doesn’t cope well with anything other than Strings and Numbers (unless your objects support a nice to_s method).

# Prints nested Hash as a nested <ul> and <li> tags
# - keys are wrapped in <strong> tags
# - values are wrapped in <span> tags
def HashToHTML(hash, opts = {})
  return if !hash.is_a?(Hash)

  indent_level = opts.fetch(:indent_level) { 0 }

  out = " " * indent_level + "<ul>\n"

  hash.each do |key, value|
    out += " " * (indent_level + 2) + "<li><strong>#{key}:</strong>"

    if value.is_a?(Hash)
      out += "\n" + HashToHTML(value, :indent_level => indent_level + 2) + " " * (indent_level + 2) + "</li>\n"
    else
      out += " <span>#{value}</span></li>\n"
    end
  end

  out += " " * indent_level + "</ul>\n"
end

Who knows, maybe someone somewhere finds it useful.

Update: much more concise solution by Piotr Szotkowski.