Critical severity9.8NVD Advisory· Published Nov 17, 2017· Updated May 13, 2026
CVE-2017-1000248
CVE-2017-1000248
Description
Redis-store <=v1.3.0 allows unsafe objects to be loaded from redis
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
redis-storeRubyGems | < 1.4.0 | 1.4.0 |
Affected products
1Patches
2ce13252c26fcMerge pull request #290 from redis-store/replace-marshalling-with-serialization
8 files changed · +80 −27
lib/redis/store/factory.rb+8 −1 modified@@ -50,7 +50,14 @@ def self.normalize_key_names(options) if options.key?(:key_prefix) && !options.key?(:namespace) options[:namespace] = options.delete(:key_prefix) # RailsSessionStore end - options[:raw] = !options[:marshalling] + options[:raw] = case + when options.key?(:serializer) + options[:serializer].nil? + when options.key?(:marshalling) + !options[:marshalling] + else + false + end options end
lib/redis/store/namespace.rb+2 −2 modified@@ -46,8 +46,8 @@ def del(*keys) def mget(*keys) options = (keys.pop if keys.last.is_a? Hash) || {} if keys.any? - # Marshalling gets extended before Namespace does, so we need to pass options further - if singleton_class.ancestors.include? Marshalling + # Serialization gets extended before Namespace does, so we need to pass options further + if singleton_class.ancestors.include? Serialization super(*keys.map {|key| interpolate(key) }, options) else super(*keys.map {|key| interpolate(key) })
lib/redis-store.rb+0 −12 modified@@ -1,13 +1 @@ -require 'redis' require 'redis/store' -require 'redis/store/factory' -require 'redis/distributed_store' -require 'redis/store/namespace' -require 'redis/store/marshalling' -require 'redis/store/version' -require 'redis/store/redis_version' - -class Redis - class Store < self - end -end
lib/redis/store.rb+26 −2 modified@@ -1,3 +1,10 @@ +require 'redis' +require 'redis/store/factory' +require 'redis/distributed_store' +require 'redis/store/namespace' +require 'redis/store/serialization' +require 'redis/store/version' +require 'redis/store/redis_version' require 'redis/store/ttl' require 'redis/store/interface' require 'redis/store/redis_version' @@ -8,6 +15,24 @@ class Store < self def initialize(options = { }) super + + unless options[:marshalling].nil? + puts %( + DEPRECATED: You are passing the :marshalling option, which has been + replaced with `serializer: Marshal` to support pluggable serialization + backends. To disable serialization (much like disabling marshalling), + pass `serializer: nil` in your configuration. + + The :marshalling option will be removed for redis-store 2.0. + ) + end + + @serializer = options.key?(:serializer) ? options[:serializer] : Marshal + + unless options[:marshalling].nil? + @serializer = options[:marshalling] ? Marshal : nil + end + _extend_marshalling options _extend_namespace options end @@ -23,8 +48,7 @@ def to_s private def _extend_marshalling(options) - @marshalling = !(options[:marshalling] === false) # HACK - TODO delegate to Factory - extend Marshalling if @marshalling + extend Serialization unless @serializer.nil? end def _extend_namespace(options)
lib/redis/store/serialization.rb+3 −3 renamed@@ -1,6 +1,6 @@ class Redis class Store < self - module Marshalling + module Serialization def set(key, value, options = nil) _marshal(value, options) { |v| super encode(key), encode(v), options } end @@ -36,11 +36,11 @@ def mset(*args) private def _marshal(val, options) - yield marshal?(options) ? Marshal.dump(val) : val + yield marshal?(options) ? @serializer.dump(val) : val end def _unmarshal(val, options) - unmarshal?(val, options) ? Marshal.load(val) : val + unmarshal?(val, options) ? @serializer.load(val) : val end def marshal?(options)
test/redis/store/factory_test.rb+37 −3 modified@@ -1,4 +1,5 @@ require 'test_helper' +require 'json' describe "Redis::Store::Factory" do describe ".create" do @@ -51,12 +52,45 @@ assert_nil(store.instance_variable_get(:@client).password) end - it "allows/disable marshalling" do - store = Redis::Store::Factory.create :marshalling => false - store.instance_variable_get(:@marshalling).must_equal(false) + it "disables serialization" do + store = Redis::Store::Factory.create :serializer => nil + store.instance_variable_get(:@serializer).must_be_nil store.instance_variable_get(:@options)[:raw].must_equal(true) end + it "configures pluggable serialization backend" do + store = Redis::Store::Factory.create :serializer => JSON + store.instance_variable_get(:@serializer).must_equal(JSON) + store.instance_variable_get(:@options)[:raw].must_equal(false) + end + + describe 'with stdout disabled' do + before do + @original_stderr = $stderr + @original_stdout = $stdout + + $stderr = Tempfile.new('stderr') + $stdout = Tempfile.new('stdout') + end + + it "disables marshalling and provides deprecation warning" do + store = Redis::Store::Factory.create :marshalling => false + store.instance_variable_get(:@serializer).must_be_nil + store.instance_variable_get(:@options)[:raw].must_equal(true) + end + + it "enables marshalling but provides warning to use :serializer instead" do + store = Redis::Store::Factory.create :marshalling => true + store.instance_variable_get(:@serializer).must_equal(Marshal) + store.instance_variable_get(:@options)[:raw].must_equal(false) + end + + after do + $stderr = @original_stderr + $stdout = @original_stdout + end + end + it "should instantiate a Redis::DistributedStore store" do store = Redis::Store::Factory.create( {:host => "localhost", :port => 6379},
test/redis/store/namespace_test.rb+2 −2 modified@@ -3,7 +3,7 @@ describe "Redis::Store::Namespace" do def setup @namespace = "theplaylist" - @store = Redis::Store.new :namespace => @namespace, :marshalling => false # TODO remove mashalling option + @store = Redis::Store.new :namespace => @namespace, :serializer => nil @client = @store.instance_variable_get(:@client) @rabbit = "bunny" @default_store = Redis::Store.new @@ -90,7 +90,7 @@ def teardown end describe 'method calls' do - let(:store){Redis::Store.new :namespace => @namespace, :marshalling => false} + let(:store){Redis::Store.new :namespace => @namespace, :serializer => nil} let(:client){store.instance_variable_get(:@client)} it "should namespace get" do
test/redis/store/serialization_test.rb+2 −2 renamed@@ -1,8 +1,8 @@ require 'test_helper' -describe "Redis::Marshalling" do +describe "Redis::Serialization" do def setup - @store = Redis::Store.new :marshalling => true + @store = Redis::Store.new serializer: Marshal @rabbit = OpenStruct.new :name => "bunny" @white_rabbit = OpenStruct.new :color => "white" @store.set "rabbit", @rabbit
e0c1398d54a9Replace marshalling with pluggable serializers
8 files changed · +80 −27
lib/redis/store/factory.rb+8 −1 modified@@ -50,7 +50,14 @@ def self.normalize_key_names(options) if options.key?(:key_prefix) && !options.key?(:namespace) options[:namespace] = options.delete(:key_prefix) # RailsSessionStore end - options[:raw] = !options[:marshalling] + options[:raw] = case + when options.key?(:serializer) + options[:serializer].nil? + when options.key?(:marshalling) + !options[:marshalling] + else + false + end options end
lib/redis/store/namespace.rb+2 −2 modified@@ -46,8 +46,8 @@ def del(*keys) def mget(*keys) options = (keys.pop if keys.last.is_a? Hash) || {} if keys.any? - # Marshalling gets extended before Namespace does, so we need to pass options further - if singleton_class.ancestors.include? Marshalling + # Serialization gets extended before Namespace does, so we need to pass options further + if singleton_class.ancestors.include? Serialization super(*keys.map {|key| interpolate(key) }, options) else super(*keys.map {|key| interpolate(key) })
lib/redis-store.rb+0 −12 modified@@ -1,13 +1 @@ -require 'redis' require 'redis/store' -require 'redis/store/factory' -require 'redis/distributed_store' -require 'redis/store/namespace' -require 'redis/store/marshalling' -require 'redis/store/version' -require 'redis/store/redis_version' - -class Redis - class Store < self - end -end
lib/redis/store.rb+26 −2 modified@@ -1,3 +1,10 @@ +require 'redis' +require 'redis/store/factory' +require 'redis/distributed_store' +require 'redis/store/namespace' +require 'redis/store/serialization' +require 'redis/store/version' +require 'redis/store/redis_version' require 'redis/store/ttl' require 'redis/store/interface' require 'redis/store/redis_version' @@ -8,6 +15,24 @@ class Store < self def initialize(options = { }) super + + unless options[:marshalling].nil? + puts %( + DEPRECATED: You are passing the :marshalling option, which has been + replaced with `serializer: Marshal` to support pluggable serialization + backends. To disable serialization (much like disabling marshalling), + pass `serializer: nil` in your configuration. + + The :marshalling option will be removed for redis-store 2.0. + ) + end + + @serializer = options.key?(:serializer) ? options[:serializer] : Marshal + + unless options[:marshalling].nil? + @serializer = options[:marshalling] ? Marshal : nil + end + _extend_marshalling options _extend_namespace options end @@ -23,8 +48,7 @@ def to_s private def _extend_marshalling(options) - @marshalling = !(options[:marshalling] === false) # HACK - TODO delegate to Factory - extend Marshalling if @marshalling + extend Serialization unless @serializer.nil? end def _extend_namespace(options)
lib/redis/store/serialization.rb+3 −3 renamed@@ -1,6 +1,6 @@ class Redis class Store < self - module Marshalling + module Serialization def set(key, value, options = nil) _marshal(value, options) { |v| super encode(key), encode(v), options } end @@ -36,11 +36,11 @@ def mset(*args) private def _marshal(val, options) - yield marshal?(options) ? Marshal.dump(val) : val + yield marshal?(options) ? @serializer.dump(val) : val end def _unmarshal(val, options) - unmarshal?(val, options) ? Marshal.load(val) : val + unmarshal?(val, options) ? @serializer.load(val) : val end def marshal?(options)
test/redis/store/factory_test.rb+37 −3 modified@@ -1,4 +1,5 @@ require 'test_helper' +require 'json' describe "Redis::Store::Factory" do describe ".create" do @@ -51,12 +52,45 @@ assert_nil(store.instance_variable_get(:@client).password) end - it "allows/disable marshalling" do - store = Redis::Store::Factory.create :marshalling => false - store.instance_variable_get(:@marshalling).must_equal(false) + it "disables serialization" do + store = Redis::Store::Factory.create :serializer => nil + store.instance_variable_get(:@serializer).must_be_nil store.instance_variable_get(:@options)[:raw].must_equal(true) end + it "configures pluggable serialization backend" do + store = Redis::Store::Factory.create :serializer => JSON + store.instance_variable_get(:@serializer).must_equal(JSON) + store.instance_variable_get(:@options)[:raw].must_equal(false) + end + + describe 'with stdout disabled' do + before do + @original_stderr = $stderr + @original_stdout = $stdout + + $stderr = Tempfile.new('stderr') + $stdout = Tempfile.new('stdout') + end + + it "disables marshalling and provides deprecation warning" do + store = Redis::Store::Factory.create :marshalling => false + store.instance_variable_get(:@serializer).must_be_nil + store.instance_variable_get(:@options)[:raw].must_equal(true) + end + + it "enables marshalling but provides warning to use :serializer instead" do + store = Redis::Store::Factory.create :marshalling => true + store.instance_variable_get(:@serializer).must_equal(Marshal) + store.instance_variable_get(:@options)[:raw].must_equal(false) + end + + after do + $stderr = @original_stderr + $stdout = @original_stdout + end + end + it "should instantiate a Redis::DistributedStore store" do store = Redis::Store::Factory.create( {:host => "localhost", :port => 6379},
test/redis/store/namespace_test.rb+2 −2 modified@@ -3,7 +3,7 @@ describe "Redis::Store::Namespace" do def setup @namespace = "theplaylist" - @store = Redis::Store.new :namespace => @namespace, :marshalling => false # TODO remove mashalling option + @store = Redis::Store.new :namespace => @namespace, :serializer => nil @client = @store.instance_variable_get(:@client) @rabbit = "bunny" @default_store = Redis::Store.new @@ -90,7 +90,7 @@ def teardown end describe 'method calls' do - let(:store){Redis::Store.new :namespace => @namespace, :marshalling => false} + let(:store){Redis::Store.new :namespace => @namespace, :serializer => nil} let(:client){store.instance_variable_get(:@client)} it "should namespace get" do
test/redis/store/serialization_test.rb+2 −2 renamed@@ -1,8 +1,8 @@ require 'test_helper' -describe "Redis::Marshalling" do +describe "Redis::Serialization" do def setup - @store = Redis::Store.new :marshalling => true + @store = Redis::Store.new serializer: Marshal @rabbit = OpenStruct.new :name => "bunny" @white_rabbit = OpenStruct.new :color => "white" @store.set "rabbit", @rabbit
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/redis-store/redis-store/commit/e0c1398d54a9661c8c70267c3a925ba6b192142envdPatchThird Party AdvisoryWEB
- github.com/advisories/GHSA-2w67-526p-gm73ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2017-1000248ghsaADVISORY
- github.com/redis-store/redis-store/commit/ce13252c26fcc40ed4935c9abfeb0ee0761e5704ghsaWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/redis-store/CVE-2017-1000248.ymlghsaWEB
News mentions
0No linked articles in our index yet.