SafeYAML
Parse (simple) YAML safely, without that pesky arbitrary code execution vulnerability.
The safe_yaml gem offers an alternative to YAML.load
suitable for accepting user input. Unlike YAML.load
, YAML.safe_load
will not expose your Ruby app to arbitrary code execution exploits (such as the one recently discovered in Rails).
Observe!
class ExploitableMap
def []=(key, value)
self.class.class_eval <<-EOS
def #{key}
return "#{value}"
end
EOS
end
end
If your application were to contain code like this and use YAML.load
anywhere on user input, an attacker could craft a YAML string to execute any code (yes, including system("unix command")
) on your servers:
> yaml = <<-EOYAML
> --- !ruby/hash:ExploitableMap
> "foo; end; puts %(I'm in yr system!); def bar": "baz"
> EOYAML
=> "--- !ruby/hash:ExploitableMap\n\"foo; end; puts %(I'm in yr system!); def bar\": \"baz\"\n"
> YAML.load(yaml)
I'm in yr system!
=> #<ExploitableMap:0x007ffadca0ca10>
With YAML.safe_load
, that attacker would be thwarted:
> YAML.safe_load(yaml)
=> {"foo; end; puts %(I'm in yr system!); def bar"=>"baz"}
SafeYAML requires Ruby 1.9.2 or newer. Maybe I'll get around to writing a Syck handler eventually, at which point it could support older versions as well.