safe_yaml 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6cf9f3e405ec65c54f30eaec331423a67877dc34
4
- data.tar.gz: 0cf7116a88485be0057ff010ab330569391a9e2e
3
+ metadata.gz: fac2ccd0e0ff144a5b72c1597d16206e9c401753
4
+ data.tar.gz: c13a8b54286042faf6c3c2caa9fd2ec6d436fe1e
5
5
  SHA512:
6
- metadata.gz: 63cb08bcc97ac6e4bf25e1da93f047f0edf1726ea404864e7e47fc920dd3c8f8df988b7e532efbb31ef6d611c24cf43577978eee12817e273e8ea254b2f55203
7
- data.tar.gz: 89be3d3d4be1c8f9dc54f7d41842a443b6d8fe71586c7d79a3002fc87a71db83809d59679f431221877fdd2fc8da3a0e88ed7b79a534b1d0cc75d2218c12f4c6
6
+ metadata.gz: f5bedc29148ac5d69c163793ef490ad22261c63ca7b390e80f4a405d62a7ccef5d91520344b6901ca785db584bbf197b0ec4a2c55170fa6b6adce6b077151f41
7
+ data.tar.gz: 77a93e398b12f8661b8fc9ab672b4d5278e5c4e2e6a7c615ee162934ad5b0c23867a94e3d2425f543563e5e04890fc76f96e7e25c99ccc8c94740c1e948212ae
data/README.md CHANGED
@@ -172,6 +172,7 @@ Also be aware that some Ruby libraries, particularly those requiring inter-proce
172
172
  1. set the `:deserialize_symbols` option to `true`,
173
173
  2. whitelist some of the types in your serialized data via `SafeYAML.whitelist!` or the `:whitelisted_tags` option, or
174
174
  3. both
175
+ - [**delayed_job**](https://github.com/collectiveidea/delayed_job): Uses YAML to serialize the objects on which delayed methods are invoked (with `delay`). The safest solution in this case is to use `SafeYAML.whitelist!` to whitelist the types you need to serialize.
175
176
  - [**Guard**](https://github.com/guard/guard): Uses YAML as a serialization format for notifications. The data serialized uses symbolic keys, so setting `SafeYAML::OPTIONS[:deserialize_symbols] = true` is necessary to allow Guard to work.
176
177
  - [**sidekiq**](https://github.com/mperham/sidekiq): Uses a YAML configiuration file with symbolic keys, so setting `SafeYAML::OPTIONS[:deserialize_symbols] = true` should allow it to work.
177
178
 
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'optparse'
6
+ require 'safe_yaml/load'
7
+
8
+ options = {}
9
+ option_parser = OptionParser.new do |opts|
10
+ opts.banner = "Usage: safe_yaml [options]"
11
+
12
+ opts.on("-f", "--file=<path>", "Parse the given YAML file, dump the result to STDOUT") do |file|
13
+ options[:file] = file
14
+ end
15
+
16
+ opts.on("--libyaml-check", "Check for libyaml vulnerability CVE-2014-2525 on your system") do
17
+ options[:libyaml_check] = true
18
+ end
19
+ end
20
+
21
+ option_parser.parse!
22
+
23
+ def report_libyaml_ok
24
+ puts "\e[32mGood news! You definitely have either a patched or up-to-date libyaml version :)\e[39m"
25
+ end
26
+
27
+ def check_for_overflow_bug
28
+ YAML.load("--- !#{'%20' * 100}")
29
+ report_libyaml_ok
30
+ end
31
+
32
+ def perform_libyaml_check(force=false)
33
+ unless SafeYAML::LibyamlChecker.libyaml_version_ok?
34
+ warn <<-EOM.gsub(/^ +/, ' ')
35
+
36
+ \e[33mSafeYAML Warning\e[39m
37
+ \e[33m----------------\e[39m
38
+
39
+ \e[31mYou may have an outdated version of libyaml (#{SafeYAML::LibyamlChecker::LIBYAML_VERSION}) installed on your system.\e[39m
40
+
41
+ Prior to 0.1.6, libyaml is vulnerable to a heap overflow exploit from malicious YAML payloads.
42
+
43
+ For more info, see:
44
+ https://www.ruby-lang.org/en/news/2014/03/29/heap-overflow-in-yaml-uri-escape-parsing-cve-2014-2525/
45
+ EOM
46
+ end
47
+
48
+ puts <<-EOM.gsub(/^ +/, ' ')
49
+
50
+ Hit Enter to check if your version of libyaml is vulnerable. This will run a test \e[31mwhich may crash\e[39m
51
+ \e[31mthe current process\e[39m. If it does, your system is vulnerable and you should do something about it.
52
+
53
+ Type "nm" and hit Enter if you don't want to run the check.
54
+
55
+ See the project wiki for more info:
56
+
57
+ https://github.com/dtao/safe_yaml/wiki/The-libyaml-vulnerability
58
+ EOM
59
+
60
+ if STDIN.readline.chomp("\n") != 'nm'
61
+ check_for_overflow_bug
62
+ end
63
+ end
64
+
65
+ if options[:libyaml_check]
66
+ perform_libyaml_check(options[:force_libyaml_check])
67
+
68
+ elsif options[:file]
69
+ yaml = File.read(options[:file])
70
+ result = SafeYAML.load(yaml)
71
+ puts result.inspect
72
+
73
+ else
74
+ puts option_parser.help
75
+ end
@@ -0,0 +1,36 @@
1
+ require "set"
2
+
3
+ module SafeYAML
4
+ class LibyamlChecker
5
+ LIBYAML_VERSION = Psych::LIBYAML_VERSION rescue nil
6
+
7
+ # Do proper version comparison (e.g. so 0.1.10 is >= 0.1.6)
8
+ SAFE_LIBYAML_VERSION = Gem::Version.new("0.1.6")
9
+
10
+ KNOWN_PATCHED_LIBYAML_VERSIONS = Set.new([
11
+ # http://people.canonical.com/~ubuntu-security/cve/2014/CVE-2014-2525.html
12
+ "0.1.4-2ubuntu0.12.04.3",
13
+ "0.1.4-2ubuntu0.12.10.3",
14
+ "0.1.4-2ubuntu0.13.10.3",
15
+ "0.1.4-3ubuntu3",
16
+
17
+ # https://security-tracker.debian.org/tracker/CVE-2014-2525
18
+ "0.1.3-1+deb6u4",
19
+ "0.1.4-2+deb7u4",
20
+ "0.1.4-3.2"
21
+ ]).freeze
22
+
23
+ def self.libyaml_version_ok?
24
+ return true if YAML_ENGINE != "psych" || defined?(JRUBY_VERSION)
25
+ return true if Gem::Version.new(LIBYAML_VERSION || "0") >= SAFE_LIBYAML_VERSION
26
+ return libyaml_patched?
27
+ end
28
+
29
+ def self.libyaml_patched?
30
+ return false if (`which dpkg` rescue '').empty?
31
+ libyaml_version = `dpkg -s libyaml-0-2`.match(/^Version: (.*)$/)
32
+ return false if libyaml_version.nil?
33
+ KNOWN_PATCHED_LIBYAML_VERSIONS.include?(libyaml_version[1])
34
+ end
35
+ end
36
+ end
@@ -1,38 +1,13 @@
1
+ require "set"
1
2
  require "yaml"
2
3
 
3
4
  # This needs to be defined up front in case any internal classes need to base
4
5
  # their behavior off of this.
5
6
  module SafeYAML
6
7
  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
31
8
  end
32
9
 
33
- SafeYAML.check_libyaml_version
34
-
35
- require "set"
10
+ require "safe_yaml/libyaml_checker"
36
11
  require "safe_yaml/deep"
37
12
  require "safe_yaml/parse/hexadecimal"
38
13
  require "safe_yaml/parse/sexagesimal"
@@ -1,3 +1,3 @@
1
1
  module SafeYAML
2
- VERSION = "1.0.2"
2
+ VERSION = "1.0.3"
3
3
  end
@@ -13,6 +13,7 @@ Gem::Specification.new do |gem|
13
13
  gem.files = `git ls-files`.split($\)
14
14
  gem.test_files = gem.files.grep(%r{^spec/})
15
15
  gem.require_paths = ["lib"]
16
+ gem.executables = ["safe_yaml"]
16
17
 
17
18
  gem.required_ruby_version = ">= 1.8.7"
18
19
  end
@@ -0,0 +1,69 @@
1
+ require "spec_helper"
2
+
3
+ describe SafeYAML::LibyamlChecker do
4
+ describe "check_libyaml_version" do
5
+ REAL_YAML_ENGINE = SafeYAML::YAML_ENGINE
6
+ REAL_LIBYAML_VERSION = SafeYAML::LibyamlChecker::LIBYAML_VERSION
7
+
8
+ let(:libyaml_patched) { false }
9
+
10
+ before :each do
11
+ SafeYAML::LibyamlChecker.stub(:libyaml_patched?).and_return(libyaml_patched)
12
+ end
13
+
14
+ after :each do
15
+ silence_warnings do
16
+ SafeYAML::YAML_ENGINE = REAL_YAML_ENGINE
17
+ SafeYAML::LibyamlChecker::LIBYAML_VERSION = REAL_LIBYAML_VERSION
18
+ end
19
+ end
20
+
21
+ def test_libyaml_version_ok(expected_result, yaml_engine, libyaml_version=nil)
22
+ silence_warnings do
23
+ SafeYAML.const_set("YAML_ENGINE", yaml_engine)
24
+ SafeYAML::LibyamlChecker.const_set("LIBYAML_VERSION", libyaml_version)
25
+ SafeYAML::LibyamlChecker.libyaml_version_ok?.should == expected_result
26
+ end
27
+ end
28
+
29
+ unless defined?(JRUBY_VERSION)
30
+ it "issues no warnings when 'Syck' is the YAML engine" do
31
+ test_libyaml_version_ok(true, "syck")
32
+ end
33
+
34
+ it "issues a warning if Psych::LIBYAML_VERSION is not defined" do
35
+ test_libyaml_version_ok(false, "psych")
36
+ end
37
+
38
+ it "issues a warning if Psych::LIBYAML_VERSION is < 0.1.6" do
39
+ test_libyaml_version_ok(false, "psych", "0.1.5")
40
+ end
41
+
42
+ it "issues no warning if Psych::LIBYAML_VERSION is == 0.1.6" do
43
+ test_libyaml_version_ok(true, "psych", "0.1.6")
44
+ end
45
+
46
+ it "issues no warning if Psych::LIBYAML_VERSION is > 0.1.6" do
47
+ test_libyaml_version_ok(true, "psych", "1.0.0")
48
+ end
49
+
50
+ it "does a proper version comparison (not just a string comparison)" do
51
+ test_libyaml_version_ok(true, "psych", "0.1.10")
52
+ end
53
+
54
+ context "when the system has a known patched libyaml version" do
55
+ let(:libyaml_patched) { true }
56
+
57
+ it "issues no warning, even when Psych::LIBYAML_VERSION < 0.1.6" do
58
+ test_libyaml_version_ok(true, "psych", "0.1.4")
59
+ end
60
+ end
61
+ end
62
+
63
+ if defined?(JRUBY_VERSION)
64
+ it "issues no warning, as JRuby doesn't use libyaml" do
65
+ test_libyaml_version_ok(true, "psych", "0.1.4")
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,14 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe YAML do
4
- # Essentially stolen from:
5
- # https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/kernel/reporting.rb#L10-25
6
- def silence_warnings
7
- $VERBOSE = nil; yield
8
- ensure
9
- $VERBOSE = true
10
- end
11
-
12
4
  def safe_load_round_trip(object, options={})
13
5
  yaml = object.to_yaml
14
6
  if SafeYAML::YAML_ENGINE == "psych"
@@ -32,47 +24,6 @@ describe YAML do
32
24
  SafeYAML.restore_defaults!
33
25
  end
34
26
 
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
-
76
27
  describe "unsafe_load" do
77
28
  if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.3"
78
29
  it "allows exploits through objects defined in YAML w/ !ruby/hash via custom :[]= methods" do
@@ -31,4 +31,12 @@ require "ostruct"
31
31
  require "hashie"
32
32
  require "heredoc_unindent"
33
33
 
34
+ # Stolen from Rails:
35
+ # https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/kernel/reporting.rb#L10-25
36
+ def silence_warnings
37
+ $VERBOSE = nil; yield
38
+ ensure
39
+ $VERBOSE = true
40
+ end
41
+
34
42
  require File.join(HERE, "resolver_specs")
metadata CHANGED
@@ -1,31 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safe_yaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
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-04-04 00:00:00.000000000 Z
11
+ date: 2014-04-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Parse YAML safely
14
14
  email: daniel.tao@gmail.com
15
- executables: []
15
+ executables:
16
+ - safe_yaml
16
17
  extensions: []
17
18
  extra_rdoc_files: []
18
19
  files:
19
- - ".gitignore"
20
- - ".travis.yml"
20
+ - .gitignore
21
+ - .travis.yml
21
22
  - CHANGES.md
22
23
  - Gemfile
23
24
  - LICENSE.txt
24
25
  - README.md
25
26
  - Rakefile
27
+ - bin/safe_yaml
26
28
  - bundle_install_all_ruby_versions.sh
27
29
  - lib/safe_yaml.rb
28
30
  - lib/safe_yaml/deep.rb
31
+ - lib/safe_yaml/libyaml_checker.rb
29
32
  - lib/safe_yaml/load.rb
30
33
  - lib/safe_yaml/parse/date.rb
31
34
  - lib/safe_yaml/parse/hexadecimal.rb
@@ -52,6 +55,7 @@ files:
52
55
  - spec/exploit.1.9.3.yaml
53
56
  - spec/issue48.txt
54
57
  - spec/issue49.yml
58
+ - spec/libyaml_checker_spec.rb
55
59
  - spec/psych_resolver_spec.rb
56
60
  - spec/resolver_specs.rb
57
61
  - spec/safe_yaml_spec.rb
@@ -74,17 +78,17 @@ require_paths:
74
78
  - lib
75
79
  required_ruby_version: !ruby/object:Gem::Requirement
76
80
  requirements:
77
- - - ">="
81
+ - - '>='
78
82
  - !ruby/object:Gem::Version
79
83
  version: 1.8.7
80
84
  required_rubygems_version: !ruby/object:Gem::Requirement
81
85
  requirements:
82
- - - ">="
86
+ - - '>='
83
87
  - !ruby/object:Gem::Version
84
88
  version: '0'
85
89
  requirements: []
86
90
  rubyforge_project:
87
- rubygems_version: 2.0.14
91
+ rubygems_version: 2.2.2
88
92
  signing_key:
89
93
  specification_version: 4
90
94
  summary: SameYAML provides an alternative implementation of YAML.load suitable for
@@ -94,6 +98,7 @@ test_files:
94
98
  - spec/exploit.1.9.3.yaml
95
99
  - spec/issue48.txt
96
100
  - spec/issue49.yml
101
+ - spec/libyaml_checker_spec.rb
97
102
  - spec/psych_resolver_spec.rb
98
103
  - spec/resolver_specs.rb
99
104
  - spec/safe_yaml_spec.rb