safe_yaml 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +15 -7
- data/lib/safe_yaml.rb +3 -2
- data/lib/safe_yaml/syck_resolver.rb +5 -5
- data/lib/safe_yaml/version.rb +1 -1
- data/spec/safe_yaml_spec.rb +11 -0
- data/spec/shared_specs.rb +31 -0
- metadata +2 -2
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
SafeYAML
|
2
2
|
========
|
3
3
|
|
4
|
+
[![Build Status](https://travis-ci.org/dtao/safe_yaml.png)](http://travis-ci.org/dtao/safe_yaml)
|
5
|
+
|
4
6
|
The **SafeYAML** gem provides an alternative implementation of `YAML.load` suitable for accepting user input in Ruby applications. Unlike Ruby's built-in implementation of `YAML.load`, SafeYAML's version will not expose apps to arbitrary code execution exploits (such as [the one recently discovered in Rails](http://www.reddit.com/r/netsec/comments/167c11/serious_vulnerability_in_ruby_on_rails_allowing/) (or [this one](http://www.h-online.com/open/news/item/Rails-developers-close-another-extremely-critical-flaw-1793511.html))).
|
5
7
|
|
6
8
|
Installation
|
@@ -50,7 +52,7 @@ Observe:
|
|
50
52
|
> "foo; end; puts %(I'm in yr system!); def bar": "baz"
|
51
53
|
> EOYAML
|
52
54
|
=> "--- !ruby/hash:ExploitableClassBuilder\n\"foo; end; puts %(I'm in yr system!); def bar\": \"baz\"\n"
|
53
|
-
|
55
|
+
|
54
56
|
> YAML.load(yaml)
|
55
57
|
I'm in yr system!
|
56
58
|
=> #<ExploitableClassBuilder:0x007fdbbe2e25d8 @class=#<Class:0x007fdbbe2e2510>>
|
@@ -81,6 +83,8 @@ By default, when you require the safe_yaml gem in your project, `YAML.load` is p
|
|
81
83
|
|
82
84
|
The default behavior can be switched to unsafe loading by calling `YAML.enable_arbitrary_object_deserialization!`. In this case, the `:safe` flag still has the same effect, but the defaults are reversed (so calling `YAML.load` will have the same behavior as if the safe_yaml gem weren't required).
|
83
85
|
|
86
|
+
This gem will also warn you whenever you use `YAML.load` without specifying the `:safe` option. If you do not want to see these messages in your logs, you can say `SafeYAML::OPTIONS[:suppress_warnings] = true` in an initializer.
|
87
|
+
|
84
88
|
Notes
|
85
89
|
-----
|
86
90
|
|
@@ -97,17 +101,21 @@ The way that SafeYAML works is by restricting the kinds of objects that can be d
|
|
97
101
|
|
98
102
|
Additionally, deserialization of symbols can be enabled by calling `YAML.enable_symbol_parsing!`.
|
99
103
|
|
104
|
+
Known Issues
|
105
|
+
------------
|
106
|
+
|
107
|
+
Also note that some Ruby libraries, particularly those requiring inter-process communication, leverage YAML's object deserialization functionality and therefore may break or otherwise be impacted by SafeYAML. The following list includes known instances of SafeYAML's interaction with other Ruby gems:
|
108
|
+
|
109
|
+
- **Guard**: Uses YAML as a serialization format for notifications. The data serialized uses symbol keys, so calling `YAML.enable_symbol_parsing!` is necessary to allow Guard to work.
|
110
|
+
|
111
|
+
The above list will grow over time, as more issues are discovered.
|
112
|
+
|
100
113
|
Caveat
|
101
114
|
------
|
102
115
|
|
103
|
-
|
116
|
+
This gem is quite young, and so the API may (read: *will*) change in future versions. The goal of the gem is to make it as easy as possible to protect existing applications from object deserialization exploits. Any and all feedback is more than welcome.
|
104
117
|
|
105
118
|
Requirements
|
106
119
|
------------
|
107
120
|
|
108
121
|
SafeYAML requires Ruby 1.8.7 or newer and works with both [Syck](http://www.ruby-doc.org/stdlib-1.8.7/libdoc/yaml/rdoc/YAML.html) and [Psych](http://github.com/tenderlove/psych).
|
109
|
-
|
110
|
-
Code Status
|
111
|
-
-------------
|
112
|
-
|
113
|
-
[![Build Status](https://secure.travis-ci.org/dtao/safe_yaml.png)](http://travis-ci.org/dtao/safe_yaml)
|
data/lib/safe_yaml.rb
CHANGED
@@ -12,7 +12,8 @@ require "safe_yaml/version"
|
|
12
12
|
module SafeYAML
|
13
13
|
OPTIONS = {
|
14
14
|
:enable_symbol_parsing => false,
|
15
|
-
:enable_arbitrary_object_deserialization => false
|
15
|
+
:enable_arbitrary_object_deserialization => false,
|
16
|
+
:suppress_warnings => false
|
16
17
|
}
|
17
18
|
end
|
18
19
|
|
@@ -131,7 +132,7 @@ module YAML
|
|
131
132
|
|
132
133
|
if safe_mode.nil?
|
133
134
|
mode = SafeYAML::OPTIONS[:enable_arbitrary_object_deserialization] ? "unsafe" : "safe"
|
134
|
-
Kernel.warn "Called '#{method}' without the :safe option -- defaulting to #{mode} mode."
|
135
|
+
Kernel.warn "Called '#{method}' without the :safe option -- defaulting to #{mode} mode." unless SafeYAML::OPTIONS[:suppress_warnings]
|
135
136
|
safe_mode = !SafeYAML::OPTIONS[:enable_arbitrary_object_deserialization]
|
136
137
|
end
|
137
138
|
|
@@ -3,15 +3,15 @@ module SafeYAML
|
|
3
3
|
QUOTE_STYLES = [:quote1, :quote2]
|
4
4
|
|
5
5
|
def resolve_node(node)
|
6
|
-
case node.
|
7
|
-
when
|
6
|
+
case node.value
|
7
|
+
when Hash
|
8
8
|
return resolve_map(node)
|
9
|
-
when
|
9
|
+
when Array
|
10
10
|
return resolve_seq(node)
|
11
|
-
when
|
11
|
+
when String
|
12
12
|
return resolve_scalar(node)
|
13
13
|
else
|
14
|
-
raise "Don't know how to resolve
|
14
|
+
raise "Don't know how to resolve this node: #{node.inspect}"
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
data/lib/safe_yaml/version.rb
CHANGED
data/spec/safe_yaml_spec.rb
CHANGED
@@ -150,6 +150,17 @@ describe YAML do
|
|
150
150
|
end
|
151
151
|
}
|
152
152
|
|
153
|
+
context "with :suppress_warnings set to true" do
|
154
|
+
before :each do SafeYAML::OPTIONS[:suppress_warnings] = true; end
|
155
|
+
after :each do SafeYAML::OPTIONS[:suppress_warnings] = false; end
|
156
|
+
|
157
|
+
it "doesn't issue a warning if :suppress_warnings option is set to true" do
|
158
|
+
SafeYAML::OPTIONS[:suppress_warnings] = true
|
159
|
+
Kernel.should_not_receive(:warn)
|
160
|
+
YAML.load(*arguments)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
153
164
|
it "issues a warning if the :safe option is omitted" do
|
154
165
|
silence_warnings do
|
155
166
|
Kernel.should_receive(:warn)
|
data/spec/shared_specs.rb
CHANGED
@@ -75,6 +75,37 @@ module SharedSpecs
|
|
75
75
|
result.should == { "foo" => "" }
|
76
76
|
end
|
77
77
|
|
78
|
+
it "correctly reverse-translates strings encoded via #to_yaml" do
|
79
|
+
parse "5.10".to_yaml
|
80
|
+
result.should == "5.10"
|
81
|
+
end
|
82
|
+
|
83
|
+
it "does not specially parse any double-quoted strings" do
|
84
|
+
parse <<-YAML
|
85
|
+
- "1"
|
86
|
+
- "3.14"
|
87
|
+
- "true"
|
88
|
+
- "false"
|
89
|
+
- "2013-02-03"
|
90
|
+
- "2013-02-03 16:27:00 -0600"
|
91
|
+
YAML
|
92
|
+
|
93
|
+
result.should == ["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"]
|
94
|
+
end
|
95
|
+
|
96
|
+
it "does not specially parse any single-quoted strings" do
|
97
|
+
parse <<-YAML
|
98
|
+
- '1'
|
99
|
+
- '3.14'
|
100
|
+
- 'true'
|
101
|
+
- 'false'
|
102
|
+
- '2013-02-03'
|
103
|
+
- '2013-02-03 16:27:00 -0600'
|
104
|
+
YAML
|
105
|
+
|
106
|
+
result.should == ["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"]
|
107
|
+
end
|
108
|
+
|
78
109
|
it "deals just fine with nested maps" do
|
79
110
|
parse <<-YAML
|
80
111
|
foo:
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe_yaml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-05 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Parse YAML safely, without that pesky arbitrary object deserialization
|
15
15
|
vulnerability
|