Skip to content

Instantly share code, notes, and snippets.

@grosser
Last active December 11, 2015 02:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grosser/4534716 to your computer and use it in GitHub Desktop.
Save grosser/4534716 to your computer and use it in GitHub Desktop.
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
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
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment