Skip to content

Commit

Permalink
Merge pull request #1460 from rack/base64-strict
Browse files Browse the repository at this point in the history
Use "strict encoding" for Base64 encoded cookies
  • Loading branch information
ioquatix committed Jan 8, 2020
2 parents a773287 + a49b0ab commit 829439f
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 12 deletions.
2 changes: 1 addition & 1 deletion lib/rack/session/cookie.rb
Expand Up @@ -52,7 +52,7 @@ class Cookie < Abstract::PersistedSecure
# Encode session cookies as Base64
class Base64
def encode(str)
::Base64.encode64(str)
::Base64.strict_encode64(str)
end

def decode(str)
Expand Down
62 changes: 51 additions & 11 deletions test/spec_session_cookie.rb
Expand Up @@ -76,26 +76,32 @@ def response_for(options = {})
it 'uses base64 to encode' do
coder = Rack::Session::Cookie::Base64.new
str = 'fuuuuu'
coder.encode(str).must_equal [str].pack('m')
coder.encode(str).must_equal [str].pack('m0')
end

it 'uses base64 to decode' do
coder = Rack::Session::Cookie::Base64.new
str = ['fuuuuu'].pack('m')
coder.decode(str).must_equal str.unpack('m').first
str = ['fuuuuu'].pack('m0')
coder.decode(str).must_equal str.unpack('m0').first
end

it 'handles non-strict base64 encoding' do
coder = Rack::Session::Cookie::Base64.new
str = ['A' * 256].pack('m')
coder.decode(str).must_equal 'A' * 256
end

describe 'Marshal' do
it 'marshals and base64 encodes' do
coder = Rack::Session::Cookie::Base64::Marshal.new
str = 'fuuuuu'
coder.encode(str).must_equal [::Marshal.dump(str)].pack('m')
coder.encode(str).must_equal [::Marshal.dump(str)].pack('m0')
end

it 'marshals and base64 decodes' do
coder = Rack::Session::Cookie::Base64::Marshal.new
str = [::Marshal.dump('fuuuuu')].pack('m')
coder.decode(str).must_equal ::Marshal.load(str.unpack('m').first)
str = [::Marshal.dump('fuuuuu')].pack('m0')
coder.decode(str).must_equal ::Marshal.load(str.unpack('m0').first)
end

it 'rescues failures on decode' do
Expand All @@ -108,13 +114,13 @@ def response_for(options = {})
it 'JSON and base64 encodes' do
coder = Rack::Session::Cookie::Base64::JSON.new
obj = %w[fuuuuu]
coder.encode(obj).must_equal [::JSON.dump(obj)].pack('m')
coder.encode(obj).must_equal [::JSON.dump(obj)].pack('m0')
end

it 'JSON and base64 decodes' do
coder = Rack::Session::Cookie::Base64::JSON.new
str = [::JSON.dump(%w[fuuuuu])].pack('m')
coder.decode(str).must_equal ::JSON.parse(str.unpack('m').first)
str = [::JSON.dump(%w[fuuuuu])].pack('m0')
coder.decode(str).must_equal ::JSON.parse(str.unpack('m0').first)
end

it 'rescues failures on decode' do
Expand All @@ -128,14 +134,14 @@ def response_for(options = {})
coder = Rack::Session::Cookie::Base64::ZipJSON.new
obj = %w[fuuuuu]
json = JSON.dump(obj)
coder.encode(obj).must_equal [Zlib::Deflate.deflate(json)].pack('m')
coder.encode(obj).must_equal [Zlib::Deflate.deflate(json)].pack('m0')
end

it 'base64 decodes, inflates, and decodes json' do
coder = Rack::Session::Cookie::Base64::ZipJSON.new
obj = %w[fuuuuu]
json = JSON.dump(obj)
b64 = [Zlib::Deflate.deflate(json)].pack('m')
b64 = [Zlib::Deflate.deflate(json)].pack('m0')
coder.decode(b64).must_equal obj
end

Expand Down Expand Up @@ -441,4 +447,38 @@ def decode(str); eval(str) if str; end
response = response_for(app: _app, cookie: response)
response.body.must_equal "1--2--"
end

it 'allows for non-strict encoded cookie' do
long_session_app = lambda do |env|
env['rack.session']['value'] = 'A' * 256
env['rack.session']['counter'] = 1
hash = env["rack.session"].dup
hash.delete("session_id")
Rack::Response.new(hash.inspect).to_a
end

non_strict_coder = Class.new {
def encode(str)
[Marshal.dump(str)].pack('m')
end

def decode(str)
return unless str

Marshal.load(str.unpack('m').first)
end
}.new

non_strict_response = response_for(app: [
long_session_app, { coder: non_strict_coder }
])

response = response_for(app: [
incrementor
], cookie: non_strict_response)

response.body.must_match %Q["value"=>"#{'A' * 256}"]
response.body.must_match '"counter"=>2'
response.body.must_match(/\A{[^}]+}\z/)
end
end

0 comments on commit 829439f

Please sign in to comment.