Skip to content

rack-session v2.1.2 produces 'invalid message' #60

Description

@andreavocado

Root Cause

rack-session 2.1.2 introduced a new V2 encryptor (AES-256-GCM) that uses Base64.strict_encode64 for cookies — standard base64 which produces +, /, and = characters.

The problem: Rack's parse_cookies_header (in rack/utils.rb) applies URI.decode_www_form_component to every cookie value, which converts + → space (a form-encoding convention that has no place in cookie parsing).

The flow:

  1. Server creates V2-encrypted session cookie with + in its base64 value
  2. Browser sends it back unchanged (browsers don't re-encode +)
  3. Rack::Utils.parse_cookies_header decodes + → space, corrupting the value
  4. Base64.strict_decode64 fails or produces garbage → guess_decryptor raises InvalidMessage, 'invalid message'
  5. Logged as: Session cookie encryptor error: invalid message

The test above shows 90% of V2 cookies will be affected. V1 cookies are immune because they use Base64.urlsafe_encode64 (- and _ instead of + and /), which URI.decode_www_form_component leaves untouched.

In 2.1.1, the single encryptor always used V1 (URL-safe base64), so this was never an issue.

test

Verify Rack corrupts V2 standard base64 cookies

require 'uri'
require 'base64'
require 'openssl'

puts '=== Does Rack corrupt V2 cookies with + in base64? ==='
puts

# Generate several random payloads to see how often + appears
plus_count = 0
100.times do
  sample = OpenSSL::Random.random_bytes(80)
  v2_encoded = Base64.strict_encode64(sample)
  after_rack = URI.decode_www_form_component(v2_encoded)
  plus_count += 1 if after_rack != v2_encoded
end
puts \"Out of 100 V2 cookies, #{plus_count} would be corrupted by Rack's URI unescape (+ -> space)\"

puts
puts '=== V1 (urlsafe_encode64) - safe from Rack unescape? ==='
plus_count_v1 = 0
100.times do
  sample = OpenSSL::Random.random_bytes(80)
  v1_encoded = Base64.urlsafe_encode64(sample)
  after_rack = URI.decode_www_form_component(v1_encoded)
  plus_count_v1 += 1 if after_rack != v1_encoded
end
puts \"Out of 100 V1 cookies, #{plus_count_v1} would be corrupted by Rack's URI unescape\"

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions