3 ms·
> YAML.load(x) or YAML.parse(x).to_ruby If you're working with attacker controlled input, at best you can avoid evals while deserializing. As soon as you use t
by mnarayan01 9y ago
> YAML.load(x) or YAML.parse(x).to_ruby
If you're working with attacker controlled input, at best you can avoid evals while deserializing. As soon as you use the result, a sufficiently clever and informed attacker can almost certainly own you. YAML is just too powerful for anything else.
If you're only using YAML as JSON with different syntax, that's a different story...but then you should just pass the library the deserialized data.
- deathanatos 9y ago> As soon as you use the result, a sufficiently clever and informed attacker can almost certainly own you. This is equivalent to saying that we should just not write any program, ever. > YAML is just too powerful for anything else. The problem the original author is getting at is that the library makes unsafe operations extremely easy to do. YAML the language is not inherently unsafe — it just serializes a data structure. But several YAML libraries (I believe both Ruby and Python are in this bucket) make it extremely easy to create objects of any arbitrary type, regardless of what the programmer expects, making arbitrary code execution either easy or trivial. Were the parse/load function something like, parse(input: serialized yaml, whitelisted_types) that only allowed reconstruction of core YAML types + whitelisted types that the user needs for his specific use case, the API would be fairly safe. (You could still shoot yourself in the whitelisted types part, of course, but again, yes, any user-controlled input handled poorly "could" be a bug.) This is a property of the construction of the API itself: the API encourages misuse.
- mnarayan01 9y agoI'm not trying to argue whether or not the API is well designed (the designers can do that if they so wish). My point is a pragmatic one: Saying the API lets you shoot yourself in the foot makes people believe that if they just use the right incantation everything will be fine and easy. YAML is just not that kind of format. If I was designing the API today, I would name YAML::load something like YAML::unsafe_load because loading YAML is dangerous. Guiding naive users to a high-restricted subset of YAML is good. Making them think that they just need to avoid "easy foot-guns" is not.
- deathanatos 9y ago> I'm not trying to argue whether or not the API is well designed (the designers can do that if they so wish). My point is a pragmatic one: Saying the API lets you shoot yourself in the foot makes people believe that if they just use the right incantation everything will be fine and easy. But that's my point: if you use the right incantation, everything should be fine-and-easy, even in languages like Ruby and Python. The larger point is that the library user shouldn't need to know the "right incantation"; the library should make the safe thing the default, and you should need to very explicitly shoot yourself in the foot. > YAML is just not that kind of format. > If I was designing the API today, I would name YAML::load something like YAML::unsafe_load because loading YAML is dangerous. Guiding naive users to a high-restricted subset of YAML is good. Making them think that they just need to avoid "easy foot-guns" is not. Reading your comment, I get the impression that you think YAML, as a format is unsafe; this isn't the case in any manner that I can see, and I explained a bit of that argument in my previous comment. The security issues have been around implementations of YAML libraries that allow the deserialization of custom tags that correspond to arbitrary language-specific objects (the !ruby tags). This isn't required by the YAML specification, and a library shouldn't do it by default because arbitrary object construction is dangerous. But YAML, as a format, doesn't require this; again, the core types + a whitelisted set of types covers 99% of use cases, and is safe. (And I think tagging is a great feature that basically appears in no other serialization format that I'm aware of. CBOR comes close, but you have to register your types w/ IANA.)
- mnarayan01 9y agoWould it be possible to create a Ruby implementation of YAML which is compliant with the YAML v1.2 spec while also avoiding the more dangerous foot-guns? Sure. But the spec is simply a means to an end, and that end -- as per http://www.yaml.org/spec/1.2/spec.html http://www.yaml.org/spec/1.2/spec.html -- is: > In contrast, YAML's foremost design goals are human readability and support for serializing arbitrary native data structures. In order to accomplish that goal in any sort of meaningful fashion, you need e.g. the !ruby tags. Hence my noting that the YAML format is not (generally) suitable for deserializing attacker controlled input. Now here's the thing: You're totally right that the "core" functionality described in the YAML spec can be quite useful for more limited purposes, including possibly even safely deserializing and using attacker controlled input with only an intermediate amount of extra legwork. For better or worse, however, that's not the purpose that the people who designed and implemented YAML were going for. Too many people who comment on how various YAML APIs should be safer (for pragmatic reasons) ignore the truly awful (pragmatic) consequences of those comments when read by people who know far less than them.