Files
codeql/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.rb

175 lines
3.9 KiB
Ruby

require "active_job"
require "base64"
require "json"
require "oj"
require "ox"
require "yaml"
class UsersController < ActionController::Base
# BAD
def route0
serialized_data = Base64.decode64 params[:key]
object = Marshal.load serialized_data
end
# BAD
def route1
serialized_data = Base64.decode64 params[:key]
object = Marshal.restore serialized_data
end
# BAD
def route2
json_data = params[:key]
object = JSON.load json_data
end
# BAD
def route3
json_data = params[:key]
object = JSON.restore json_data
end
# GOOD - JSON.parse is safe to use on untrusted data
def route4
json_data = params[:key]
object = JSON.parse json_data
end
# BAD
def route5
yaml_data = params[:key]
object = YAML.load yaml_data
end
# GOOD
def route6
yaml_data = params[:key]
object = YAML.safe_load yaml_data
end
# BAD - Oj.load is unsafe in its default :object mode
def route7
json_data = params[:key]
object = Oj.load json_data
object = Oj.load json_data, mode: :object
end
# GOOD - Oj.load is safe in any other mode
def route8
json_data = params[:key]
# Test the different ways the options hash can be passed
options = { allow_blank: true, mode: :rails }
object1 = Oj.load json_data, options
object2 = Oj.load json_data, mode: :strict
object3 = Oj.load json_data, :allow_blank => true, :mode => :compat
# TODO: false positive; we aren't detecting flow from `:json` to the call argument.
more_options = { allow_blank: true }
more_options[:mode] = :json
object4 = Oj.load json_data, more_options
end
# GOOD
def route9
json_data = params[:key]
object = Oj.safe_load json_data
end
# BAD - Oj.object_load is always unsafe
def route10
json_data = params[:key]
object = Oj.object_load json_data
end
# BAD - Ox.parse_obj is always unsafe
def route11
xml_data = params[:key]
object = Ox.parse_obj xml_data
end
# BAD - Ox.load with :object mode is always unsafe
def route12
xml_data = params[:key]
object = Ox.load xml_data, mode: :object
end
# GOOD - Ox.load is safe in the default mode (which is :generic) and in any other mode than :object
def route13
xml_data = params[:key]
object1 = Ox.load xml_data
object2 = Ox.load xml_data, mode: :limited
object3 = Ox.load xml_data, mode: :hash
object4 = Ox.load xml_data, mode: :generic
end
# BAD - `Hash.from_trusted_xml` will deserialize elements with the
# `type="yaml"` attribute as YAML.
def route14
xml = params[:key]
hash = Hash.from_trusted_xml(xml)
end
# BAD before psych version 4.0.0
def route15
yaml_data = params[:key]
object = Psych.load yaml_data
object = Psych.load_file yaml_data
end
# GOOD In psych version 4.0.0 and above
def route16
yaml_data = params[:key]
object = Psych.load yaml_data
object = Psych.load_file yaml_data
end
# GOOD
def route17
yaml_data = params[:key]
object = Psych.parse_stream(yaml_data)
object = Psych.parse(yaml_data)
object = Psych.parse_file(yaml_data)
end
# BAD
def route18
yaml_data = params[:key]
object = Psych.unsafe_load(yaml_data)
object = Psych.unsafe_load_file(yaml_data)
object = Psych.load_stream(yaml_data)
parse_output = Psych.parse_stream(yaml_data)
object = parse_output.to_ruby
object = Psych.parse(yaml_data).to_ruby
object = Psych.parse_file(yaml_data).to_ruby
end
# BAD
def route19
plist_data = params[:key]
result = Plist.parse_xml(plist_data)
result = Plist.parse_xml(plist_data, marshal: true)
end
# GOOD
def route20
plist_data = params[:key]
result = Plist.parse_xml(plist_data, marshal: false)
end
def stdin
object = YAML.load $stdin.read
# STDIN
object = YAML.load STDIN.gets
# ARGF
object = YAML.load ARGF.read
# Kernel.gets
object = YAML.load gets
# Kernel.readlines
object = YAML.load readlines
end
end