public
Last active

Rails 2.3 fix for https://github.com/rails/rails/issues/8832 / CVE-2013-0155 prevent nil insertion, do a deep_munge for all non-browser input methods (which cannot produce empty hash or array or nil) ActiveRecord does not need the empty hash patch since e.g. `User.find_by_name({})` is ok

  • Download Gist
fix.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
if Rails::VERSION::MAJOR == 2
ActionController::Base.class_eval do
def params_with_nil_fix
params = params_without_nil_fix
unless params.instance_variable_get(:@nil_fixed)
params.instance_variable_set(:@nil_fixed, true)
 
# normal form params cannot include nil/empty hash/empty array, just json/xml
deep_munge(params) unless ["application/x-www-form-urlencoded", "multipart/form-data", nil].include?(request.try(:content_type))
end
params
end
alias_method_chain :params, :nil_fix
 
# copied from https://github.com/rails/rails/blob/d5cd97baa44fa66dc681041a213092b45c57c32f/actionpack/lib/action_dispatch/http/request.rb:250
def deep_munge(hash)
hash.each do |k, v|
case v
when Array
v.grep(Hash) { |x| deep_munge(x) }
v.compact!
hash[k] = nil if v.empty?
when Hash
deep_munge(v)
end
end
 
hash
end unless defined?(deep_munge)
end
end
fix_test.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
require File.expand_path("../../../helpers/test_helper", File.dirname(__FILE__))
 
# fixed in 3.2.11 via https://github.com/rails/rails/commit/d5cd97baa44fa66dc681041a213092b45c57c32
 
class PreventNilValuesInParamsTest < ActionController::IntegrationTest
class TestController < ActionController::Base
def index
render :text => params.except(:action, :controller).inspect
end
end
context "prevent nil values in params" do
let(:xpath){ "/test_route/prevent_nil_values_in_params_test/" }
 
should "have normal params" do
get xpath, :id => ["a", {"b" => 1}]
assert_equal "{\"id\"=>[\"a\", {\"b\"=>\"1\"}]}", @response.body
end
 
# works in real server, not in integration test
should_eventually "have nil for weirdly nested params" do
get "#{xpath}?a[][]&b[][]=1"
assert_equal "{\"a\"=>nil,\"b\"=>nil}", @response.body
end
 
should "have empty strings" do
get xpath, :id => " "
assert_equal "{\"id\"=>\" \"}", @response.body
end
 
context "xml" do
should "remove nil in arrays" do
post xpath, "<id type=\"array\"><id>xxx</id><id nil=\"true\"/></id>", 'CONTENT_TYPE' => Mime::XML.to_s
assert_equal "{\"id\"=>[\"xxx\"]}", @response.body
end
 
should "not allow empty arrays" do
post xpath, "<hash><id type=\"array\"></id><foo></foo></hash>", 'CONTENT_TYPE' => Mime::XML.to_s
assert_equal "{\"hash\"=>{\"id\"=>nil, \"foo\"=>nil}}", @response.body
end
end
 
context "json" do
should "remove nil in arrays" do
post xpath, "{\"id\":[\"xxx\", null]}", 'CONTENT_TYPE' => Mime::JSON.to_s
assert_equal "{\"id\"=>[\"xxx\"]}", @response.body
end
 
should "not allow empty arrays" do
post xpath, "{\"id\":[],\"foo\":{}}", 'CONTENT_TYPE' => Mime::JSON.to_s
assert_equal "{\"id\"=>nil, \"foo\"=>{}}", @response.body
end
end
 
should "apply to funky shit" do
post xpath, "{\"id\":[\"xxx\", null]}", 'CONTENT_TYPE' => "image/jpeg"
assert_equal "{}", @response.body
end
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.