> The ruby 2.1 behavior of serializing out as a Time but then parsing back in to a String anyway -- seems particularly sketchy, and ripe for roundtrip bugs where the string it gets turned into on parse isn't _quite_ the same one that was original before serialization. (Say, winds up with a different timezone or something).
It's not serializing it out as a time, but serializing it as an "implicit string" (a string with no quotes). When Psych goes to dump the string out, it checks to see if the string could be interpreted as something else. Since the string being dumped doesn't match a YAML timestamp, it doesn't add explicit quoting on the string.
Here's an example. From the blog post, they are doing this:
Psych.dump Time.now.utc.strftime("%Y-%m-%d %H:%M:%S.%6N %Z")
Output:
"--- 2014-05-23 15:42:29.882127 UTC\n...\n"
The `strftime` adds the string "UTC" to the timestamp. But "UTC" isn't part of the [yaml timestamp spec](
http://yaml.org/type/timestamp.html). Since it doesn't match a YAML timestamp, Psych dumps it out as an implicit string.
If we change the `strftime` to produce a string that does look like a YAML timestamp like this:
Psych.dump Time.now.utc.strftime("%Y-%m-%d %H:%M:%S.%6N %z")
Output:
"--- '2014-05-23 15:46:31.197338 +0000'\n"
Then the output is quoted so that when we load it isn't ambiguous (quoted strings are
always considered strings, and are never candidates for coercion). If we were to manually modify that YAML and remove the quotes, it is indeed converted to a Time object:
irb(main):012:0> Psych.load "--- '2014-05-23 15:46:31.197338 +0000'\n"
=> "2014-05-23 15:46:31.197338 +0000"
irb(main):013:0> Psych.load "--- 2014-05-23 15:46:31.197338 +0000\n"
=> 2014-05-23 08:46:31 -0700
The article says:
>The same would happen in Psych 2.0.5 if it were not for a new feature called Safe Load which was introduced after the recent Rails YAML deserialisation security vulnerabilities.
I have no idea where they got this. You have to explicitly call `safe_load`, and it doesn't sound like they're doing that. If your format the timestamp correctly in your YAML, it will happily deserialize as a Time object. :-/