safe_yaml 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a072651152f97592749563e45a793b71928ed80
4
- data.tar.gz: 0de35cc4fefc6f0f98d81c5ef1284382e47c8e3c
3
+ metadata.gz: 6cf9f3e405ec65c54f30eaec331423a67877dc34
4
+ data.tar.gz: 0cf7116a88485be0057ff010ab330569391a9e2e
5
5
  SHA512:
6
- metadata.gz: 4b3b766d2e7b1d211d8645a57ab3dfefd253cebd29fb7981f792e7194fd66b61d8fc21213088b67420481d1baeb12aad35b024f0d19cf3164c2c756151b45b75
7
- data.tar.gz: 457535a8deac214dd3e898d2f38ed654c2c854d76572644d2255ef4fa2040fdd4c1d509c9c197983e84e687dd77f6ac0bcd5686032a4067cf72161fdcd998cbf
6
+ metadata.gz: 63cb08bcc97ac6e4bf25e1da93f047f0edf1726ea404864e7e47fc920dd3c8f8df988b7e532efbb31ef6d611c24cf43577978eee12817e273e8ea254b2f55203
7
+ data.tar.gz: 89be3d3d4be1c8f9dc54f7d41842a443b6d8fe71586c7d79a3002fc87a71db83809d59679f431221877fdd2fc8da3a0e88ed7b79a534b1d0cc75d2218c12f4c6
data/.gitignore CHANGED
@@ -1,2 +1 @@
1
1
  Gemfile.lock
2
- dist/
data/CHANGES.md CHANGED
@@ -1,3 +1,22 @@
1
+ 1.0.2
2
+ -----
3
+
4
+ - added warning when using Psych + an older version of libyaml
5
+
6
+ 1.0.1
7
+ -----
8
+
9
+ - fixed handling for strings that look like (invalid) dates
10
+
11
+ 1.0.0
12
+ -----
13
+
14
+ - updated date parsing to use local timezone
15
+ - **now requiring "safe_yaml/load" provides `SafeYAML.load` without clobbering `YAML`**
16
+ - fixed handling of empty files
17
+ - fixed some (edge case) integer parsing bugs
18
+ - fixed some JRuby-specific issues
19
+
1
20
  0.9.7
2
21
  -----
3
22
 
@@ -33,21 +33,19 @@ module YAML
33
33
  SafeYAML.load_file(*args)
34
34
  end
35
35
 
36
- def self.unsafe_load_file(filename)
37
- if SafeYAML::MULTI_ARGUMENT_YAML_LOAD
36
+ if SafeYAML::MULTI_ARGUMENT_YAML_LOAD
37
+ def self.unsafe_load_file(filename)
38
38
  # https://github.com/tenderlove/psych/blob/v1.3.2/lib/psych.rb#L296-298
39
39
  File.open(filename, 'r:bom|utf-8') { |f| self.unsafe_load(f, filename) }
40
- else
40
+ end
41
+
42
+ else
43
+ def self.unsafe_load_file(filename)
41
44
  # https://github.com/tenderlove/psych/blob/v1.2.2/lib/psych.rb#L231-233
42
45
  self.unsafe_load File.open(filename)
43
46
  end
44
47
  end
45
48
 
46
- def self.unsafe_load_file(filename)
47
- # https://github.com/indeyets/syck/blob/master/ext/ruby/lib/yaml.rb#L133-135
48
- File.open(filename) { |f| self.unsafe_load(f) }
49
- end
50
-
51
49
  class << self
52
50
  alias_method :unsafe_load, :load
53
51
  alias_method :load, :load_with_options
@@ -4,8 +4,34 @@ require "yaml"
4
4
  # their behavior off of this.
5
5
  module SafeYAML
6
6
  YAML_ENGINE = defined?(YAML::ENGINE) ? YAML::ENGINE.yamler : "syck"
7
+ LIBYAML_VERSION = YAML_ENGINE == "psych" && Psych.const_defined?("LIBYAML_VERSION", false) ? Psych::LIBYAML_VERSION : nil
8
+
9
+ def self.check_libyaml_version
10
+ if YAML_ENGINE == "psych" && (LIBYAML_VERSION.nil? || LIBYAML_VERSION < "0.1.6")
11
+ Kernel.warn <<-EOWARNING.gsub(/^ +/, ' ')
12
+
13
+ \e[33mSafeYAML Warning\e[39m
14
+ \e[33m----------------\e[39m
15
+
16
+ \e[31mYou appear to have an outdated version of libyaml (#{LIBYAML_VERSION}) installed on your system.\e[39m
17
+
18
+ Prior to 0.1.6, libyaml is vulnerable to a heap overflow exploit from malicious YAML payloads.
19
+
20
+ For more info, see:
21
+ https://www.ruby-lang.org/en/news/2014/03/29/heap-overflow-in-yaml-uri-escape-parsing-cve-2014-2525/
22
+
23
+ The easiest thing to do right now is probably to update Psych to the latest version and enable
24
+ the 'bundled-libyaml' option, which will install a vendored libyaml with the vulnerability patched:
25
+
26
+ \e[32mgem install psych -- --enable-bundled-libyaml\e[39m
27
+
28
+ EOWARNING
29
+ end
30
+ end
7
31
  end
8
32
 
33
+ SafeYAML.check_libyaml_version
34
+
9
35
  require "set"
10
36
  require "safe_yaml/deep"
11
37
  require "safe_yaml/parse/hexadecimal"
@@ -36,7 +62,28 @@ module SafeYAML
36
62
 
37
63
  OPTIONS = Deep.copy(DEFAULT_OPTIONS)
38
64
 
65
+ PREDEFINED_TAGS = {}
66
+
67
+ if YAML_ENGINE == "syck"
68
+ YAML.tagged_classes.each do |tag, klass|
69
+ PREDEFINED_TAGS[klass] = tag
70
+ end
71
+
72
+ else
73
+ # Special tags appear to be hard-coded in Psych:
74
+ # https://github.com/tenderlove/psych/blob/v1.3.4/lib/psych/visitors/to_ruby.rb
75
+ # Fortunately, there aren't many that SafeYAML doesn't already support.
76
+ PREDEFINED_TAGS.merge!({
77
+ Exception => "!ruby/exception",
78
+ Range => "!ruby/range",
79
+ Regexp => "!ruby/regexp",
80
+ })
81
+ end
82
+
83
+ Deep.freeze(PREDEFINED_TAGS)
84
+
39
85
  module_function
86
+
40
87
  def restore_defaults!
41
88
  OPTIONS.clear.merge!(Deep.copy(DEFAULT_OPTIONS))
42
89
  end
@@ -61,7 +108,7 @@ module SafeYAML
61
108
  raise "#{klass} cannot be anonymous" if klass_name.nil? || klass_name.empty?
62
109
 
63
110
  # Whitelist any built-in YAML tags supplied by Syck or Psych.
64
- predefined_tag = predefined_tags[klass]
111
+ predefined_tag = PREDEFINED_TAGS[klass]
65
112
  if predefined_tag
66
113
  OPTIONS[:whitelisted_tags] << predefined_tag
67
114
  return
@@ -78,30 +125,6 @@ module SafeYAML
78
125
  OPTIONS[:whitelisted_tags] << "#{tag_prefix}:#{klass_name}"
79
126
  end
80
127
 
81
- def predefined_tags
82
- if @predefined_tags.nil?
83
- @predefined_tags = {}
84
-
85
- if YAML_ENGINE == "syck"
86
- YAML.tagged_classes.each do |tag, klass|
87
- @predefined_tags[klass] = tag
88
- end
89
-
90
- else
91
- # Special tags appear to be hard-coded in Psych:
92
- # https://github.com/tenderlove/psych/blob/v1.3.4/lib/psych/visitors/to_ruby.rb
93
- # Fortunately, there aren't many that SafeYAML doesn't already support.
94
- @predefined_tags.merge!({
95
- Exception => "!ruby/exception",
96
- Range => "!ruby/range",
97
- Regexp => "!ruby/regexp",
98
- })
99
- end
100
- end
101
-
102
- @predefined_tags
103
- end
104
-
105
128
  if YAML_ENGINE == "psych"
106
129
  def tag_is_explicitly_trusted?(tag)
107
130
  false
@@ -19,7 +19,7 @@ module SafeYAML
19
19
 
20
20
  # The DateTime class has a #to_time method in Ruby 1.9+;
21
21
  # Before that we'll just need to convert DateTime to Time ourselves.
22
- TO_TIME_AVAILABLE = DateTime.new.respond_to?(:to_time)
22
+ TO_TIME_AVAILABLE = DateTime.instance_methods.include?(:to_time)
23
23
 
24
24
  def self.value(value)
25
25
  d = DateTime.parse(value)
@@ -1,3 +1,3 @@
1
1
  module SafeYAML
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "spec_helper")
1
+ require "spec_helper"
2
2
 
3
3
  if SafeYAML::YAML_ENGINE == "psych"
4
4
  require "safe_yaml/psych_resolver"
@@ -16,8 +16,31 @@ module ResolverSpecs
16
16
 
17
17
  # Isn't this how I should've been doing it all along?
18
18
  def parse_and_test(yaml)
19
- parse(yaml)
20
- @result.should == YAML.unsafe_load(yaml)
19
+ safe_result = parse(yaml)
20
+
21
+ exception_thrown = nil
22
+
23
+ unsafe_result = begin
24
+ YAML.unsafe_load(yaml)
25
+ rescue Exception => e
26
+ exception_thrown = e
27
+ end
28
+
29
+ if exception_thrown
30
+ # If the underlying YAML parser (e.g. Psych) threw an exception, I'm
31
+ # honestly not sure what the right thing to do is. For now I'll just
32
+ # print a warning. Should SafeYAML fail when Psych fails?
33
+ Kernel.warn "\n"
34
+ Kernel.warn "Discrepancy between SafeYAML and #{SafeYAML::YAML_ENGINE} on input:\n"
35
+ Kernel.warn "#{yaml.unindent}\n"
36
+ Kernel.warn "SafeYAML result:"
37
+ Kernel.warn "#{safe_result.inspect}\n"
38
+ Kernel.warn "#{SafeYAML::YAML_ENGINE} result:"
39
+ Kernel.warn "#{exception_thrown.inspect}\n"
40
+
41
+ else
42
+ safe_result.should == unsafe_result
43
+ end
21
44
  end
22
45
 
23
46
  context "by default" do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "spec_helper")
1
+ require "spec_helper"
2
2
 
3
3
  describe YAML do
4
4
  # Essentially stolen from:
@@ -32,6 +32,47 @@ describe YAML do
32
32
  SafeYAML.restore_defaults!
33
33
  end
34
34
 
35
+ describe "check_libyaml_version" do
36
+ REAL_YAML_ENGINE = SafeYAML::YAML_ENGINE
37
+ REAL_LIBYAML_VERSION = SafeYAML::LIBYAML_VERSION
38
+
39
+ after :each do
40
+ silence_warnings do
41
+ SafeYAML::YAML_ENGINE = REAL_YAML_ENGINE
42
+ SafeYAML::LIBYAML_VERSION = REAL_LIBYAML_VERSION
43
+ end
44
+ end
45
+
46
+ def test_check_libyaml_version(warning_expected, yaml_engine, libyaml_version=nil)
47
+ silence_warnings do
48
+ SafeYAML.const_set("YAML_ENGINE", yaml_engine)
49
+ SafeYAML.const_set("LIBYAML_VERSION", libyaml_version)
50
+ Kernel.send(warning_expected ? :should_receive : :should_not_receive, :warn)
51
+ SafeYAML.check_libyaml_version
52
+ end
53
+ end
54
+
55
+ it "issues no warnings when 'Syck' is the YAML engine" do
56
+ test_check_libyaml_version(false, "syck")
57
+ end
58
+
59
+ it "issues a warning if Psych::LIBYAML_VERSION is not defined" do
60
+ test_check_libyaml_version(true, "psych")
61
+ end
62
+
63
+ it "issues a warning if Psych::LIBYAML_VERSION is < 0.1.6" do
64
+ test_check_libyaml_version(true, "psych", "0.1.5")
65
+ end
66
+
67
+ it "issues no warning if Psych::LIBYAML_VERSION is == 0.1.6" do
68
+ test_check_libyaml_version(false, "psych", "0.1.6")
69
+ end
70
+
71
+ it "issues no warning if Psych::LIBYAML_VERSION is > 0.1.6" do
72
+ test_check_libyaml_version(false, "psych", "1.0.0")
73
+ end
74
+ end
75
+
35
76
  describe "unsafe_load" do
36
77
  if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.3"
37
78
  it "allows exploits through objects defined in YAML w/ !ruby/hash via custom :[]= methods" do
@@ -7,12 +7,19 @@ $LOAD_PATH << File.join(HERE, "support")
7
7
  require "yaml"
8
8
  if ENV["YAMLER"] && defined?(YAML::ENGINE)
9
9
  YAML::ENGINE.yamler = ENV["YAMLER"]
10
- puts "Running specs in Ruby #{RUBY_VERSION} with '#{YAML::ENGINE.yamler}' YAML engine."
11
10
  end
12
11
 
13
- if defined?(JRUBY_VERSION) && ENV["JRUBY_OPTS"]
14
- puts "Running JRuby in #{RUBY_VERSION} mode."
15
- end
12
+ ruby_version = defined?(JRUBY_VERSION) ? "JRuby #{JRUBY_VERSION} in #{RUBY_VERSION} mode" : "Ruby #{RUBY_VERSION}"
13
+ yaml_engine = defined?(YAML::ENGINE) ? YAML::ENGINE.yamler : "syck"
14
+ libyaml_version = yaml_engine == "psych" && Psych.const_defined?("LIBYAML_VERSION", false) ? Psych::LIBYAML_VERSION : "N/A"
15
+
16
+ puts <<-EOM
17
+
18
+ Running #{ruby_version} with '#{yaml_engine}' YAML engine.
19
+ YAML engine version: #{YAML::VERSION}
20
+ libyaml version: #{libyaml_version}
21
+
22
+ EOM
16
23
 
17
24
  # Caching references to these methods before loading safe_yaml in order to test
18
25
  # that they aren't touched unless you actually require safe_yaml (see yaml_spec.rb).
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "spec_helper")
1
+ require "spec_helper"
2
2
 
3
3
  if SafeYAML::YAML_ENGINE == "syck"
4
4
  require "safe_yaml/syck_resolver"
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "..", "spec_helper")
1
+ require "spec_helper"
2
2
 
3
3
  describe SafeYAML::Transform do
4
4
  it "should return the same encoding when decoding Base64" do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "..", "spec_helper")
1
+ require "spec_helper"
2
2
 
3
3
  describe SafeYAML::Transform::ToDate do
4
4
  it "returns true when the value matches a valid Date" do
@@ -36,7 +36,7 @@ describe SafeYAML::Transform::ToDate do
36
36
  success, result = subject.transform?("2012-12-01 10:33:45 +11:00")
37
37
  success.should be_true
38
38
  result.should == Time.utc(2012, 11, 30, 23, 33, 45)
39
- result.gmt_offset.should == Time.now.gmt_offset
39
+ result.gmt_offset.should == Time.local(2012, 11, 30).gmt_offset
40
40
  end
41
41
 
42
42
  it "returns strings for invalid dates" do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "..", "spec_helper")
1
+ require "spec_helper"
2
2
 
3
3
  describe SafeYAML::Transform::ToFloat do
4
4
  it "returns true when the value matches a valid Float" do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "..", "spec_helper")
1
+ require "spec_helper"
2
2
 
3
3
  describe SafeYAML::Transform::ToInteger do
4
4
  it "returns true when the value matches a valid Integer" do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "..", "spec_helper")
1
+ require "spec_helper"
2
2
 
3
3
  describe SafeYAML::Transform::ToSymbol do
4
4
  def with_symbol_deserialization_value(value)
@@ -1,6 +1,6 @@
1
1
  # See https://github.com/dtao/safe_yaml/issues/47
2
2
 
3
- require File.join(File.dirname(__FILE__), "spec_helper")
3
+ require "spec_helper"
4
4
 
5
5
  describe YAML do
6
6
  context "when you've only required safe_yaml/load", :libraries => true do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safe_yaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Tao
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-10 00:00:00.000000000 Z
11
+ date: 2014-04-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Parse YAML safely
14
14
  email: daniel.tao@gmail.com
@@ -16,8 +16,8 @@ executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
- - .gitignore
20
- - .travis.yml
19
+ - ".gitignore"
20
+ - ".travis.yml"
21
21
  - CHANGES.md
22
22
  - Gemfile
23
23
  - LICENSE.txt
@@ -74,12 +74,12 @@ require_paths:
74
74
  - lib
75
75
  required_ruby_version: !ruby/object:Gem::Requirement
76
76
  requirements:
77
- - - '>='
77
+ - - ">="
78
78
  - !ruby/object:Gem::Version
79
79
  version: 1.8.7
80
80
  required_rubygems_version: !ruby/object:Gem::Requirement
81
81
  requirements:
82
- - - '>='
82
+ - - ">="
83
83
  - !ruby/object:Gem::Version
84
84
  version: '0'
85
85
  requirements: []