Posted 8 months ago. Visible to the public.

Ruby: The YAML safe_load method hides some pitfalls

The Ruby standard lib ships with a YAML Parser called Psych. But serializing and deserializing data seems not as obvious as if you are using JSON.

To safely write and read YAML files you should use Psych#dump (String#to_yaml) and Psych.safe_load (YAML.safe_load):

data = {'key' => 'value'}.to_yaml => "---\nkey: value\n" YAML.safe_load(data) => {"key"=>"value"}

Unfortunately you might encounter a few pitfalls which are not obvious in the first place. All of them are a side effect that you can not configure Psych#dump to only write safe data.

Pitfall 1: Psych::DisallowedClass

Psych#safe_load only whitelists the following classes: TrueClass, FalseClass, NilClass, Numeric, String, Array and Hash. All other classes will raise an exception unless you whitelist them. Maybe it is a good idea to add Symbol, Date and Time to that list, but other classes could also make sense.

data = {foo: 'bar'}.to_yaml ::YAML.safe_load(data) Psych::DisallowedClass: Tried to load unspecified class: Symbol ::YAML.safe_load(data, [Symbol]) => {:foo=>"bar"}

Pitfall 2: Psych::BadAlias

Psych#dump will create aliases if you reference the same object more than one time. By default this is disabled by Psych#safe_load. If you use the default whitelist you will not encounter the issue, but for "more complex" classes (e.g. Time) Psych#dump will optimize the result.

time = data = {foo: time, bar: time}.to_yaml => => "---\n:foo: &1 2019-11-08 11:28:34.834180510 +01:00\n:bar: *1\n" ::YAML.safe_load(data, [Symbol, Time]) Psych::BadAlias: Unknown alias: 1 ::YAML.safe_load(data, [Symbol, Time], [], true) # This sym => {:foo=>2019-11-08 11:28:34 +0100, :bar=>2019-11-08 11:28:34 +0100}

A note

Note that both these options are there for a reason:

Allowing to deserialize symbols can expose an application to a DOS attack (since symbols are not garbage-collectable).

Parsing aliases allows "YAML bombs" that also constitute a DOS attack.

You have to choose if this is acceptable risk for your use case.

By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.

Owner of this card:

Emanuel De
Last edit:
11 days ago
by Dominik Schöler
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Emanuel De to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more