Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rubygem-rack-session for 
openSUSE:Factory checked in at 2026-04-22 17:02:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-rack-session (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-rack-session.new.11940 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-rack-session"

Wed Apr 22 17:02:03 2026 rev:4 rq:1348749 version:2.1.2

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/rubygem-rack-session/rubygem-rack-session.changes    
    2025-10-10 17:09:46.326311997 +0200
+++ 
/work/SRC/openSUSE:Factory/.rubygem-rack-session.new.11940/rubygem-rack-session.changes
     2026-04-22 17:02:37.003483098 +0200
@@ -1,0 +2,6 @@
+Wed Apr 22 08:37:09 UTC 2026 - Aleksei Burlakov <[email protected]>
+
+- New upstream release 2.1.2
+  * Fixed:  crafted session cookie don't lead to gain unauthorized access 
[CVE-2026-39324][bsc#1261831]
+
+-------------------------------------------------------------------

Old:
----
  rack-session-2.1.1.gem

New:
----
  rack-session-2.1.2.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-rack-session.spec ++++++
--- /var/tmp/diff_new_pack.45IVru/_old  2026-04-22 17:02:37.759513316 +0200
+++ /var/tmp/diff_new_pack.45IVru/_new  2026-04-22 17:02:37.767513636 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-rack-session
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-rack-session
-Version:        2.1.1
+Version:        2.1.2
 Release:        0
 %define mod_name rack-session
 %define mod_full_name %{mod_name}-%{version}

++++++ rack-session-2.1.1.gem -> rack-session-2.1.2.gem ++++++
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/session/cookie.rb 
new/lib/rack/session/cookie.rb
--- old/lib/rack/session/cookie.rb      2025-05-06 12:54:56.000000000 +0200
+++ new/lib/rack/session/cookie.rb      1980-01-02 01:00:00.000000000 +0100
@@ -237,8 +237,10 @@
               # Decode using legacy HMAC decoder
               session_data = @legacy_hmac_coder.decode(session_data)
 
-            elsif !session_data && coder
-              # Use the coder option, which has the potential to be very unsafe
+            elsif !session_data && encryptors.empty? && coder
+              # Use the coder option, which has the potential to be very 
unsafe.
+              # This path is only reached when no encryptors (secrets:) are 
configured;
+              # if encryptors are present but decryption failed, the cookie is 
rejected.
               session_data = coder.decode(cookie_data)
             end
           end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/session/encryptor.rb 
new/lib/rack/session/encryptor.rb
--- old/lib/rack/session/encryptor.rb   2025-05-06 12:54:56.000000000 +0200
+++ new/lib/rack/session/encryptor.rb   1980-01-02 01:00:00.000000000 +0100
@@ -5,9 +5,9 @@
 # Copyright, 2022, by Philip Arndt.
 
 require 'base64'
+require 'json'
 require 'openssl'
 require 'securerandom'
-require 'zlib'
 
 require 'rack/utils'
 
@@ -23,169 +23,392 @@
       class InvalidMessage < Error
       end
 
-      # The secret String must be at least 64 bytes in size. The first 32 bytes
-      # will be used for the encryption cipher key. The remainder will be used
-      # for an HMAC key.
-      #
-      # Options may include:
-      # * :serialize_json
-      #     Use JSON for message serialization instead of Marshal. This can be
-      #     viewed as a security enhancement.
-      # * :pad_size
-      #     Pad encrypted message data, to a multiple of this many bytes
-      #     (default: 32). This can be between 2-4096 bytes, or +nil+ to 
disable
-      #     padding.
-      # * :purpose
-      #     Limit messages to a specific purpose. This can be viewed as a
-      #     security enhancement to prevent message reuse from different 
contexts
-      #     if keys are reused.
-      #
-      # Cryptography and Output Format:
-      #
-      #   urlsafe_encode64(version + random_data + IV + encrypted data + HMAC)
-      #
-      #  Where:
-      #  * version - 1 byte and is currently always 0x01
-      #  * random_data - 32 bytes used for generating the per-message secret
-      #  * IV - 16 bytes random initialization vector
-      #  * HMAC - 32 bytes HMAC-SHA-256 of all preceding data, plus the purpose
-      #    value
-      def initialize(secret, opts = {})
-        raise ArgumentError, "secret must be a String" unless String === secret
-        raise ArgumentError, "invalid secret: #{secret.bytesize}, must be 
>=64" unless secret.bytesize >= 64
+      module Serializable
+        private
+
+        # Returns a serialized payload of the message. If a :pad_size is 
supplied,
+        # the message will be padded. The first 2 bytes of the returned string 
will
+        # indicating the amount of padding.
+        def serialize_payload(message)
+          serialized_data = serializer.dump(message)
+
+          return 
"#{[0].pack('v')}#{serialized_data.force_encoding(Encoding::BINARY)}" if 
@options[:pad_size].nil?
+
+          padding_bytes = @options[:pad_size] - (2 + serialized_data.size) % 
@options[:pad_size]
+          padding_data = SecureRandom.random_bytes(padding_bytes)
+
+          
"#{[padding_bytes].pack('v')}#{padding_data}#{serialized_data.force_encoding(Encoding::BINARY)}"
+        end
+
+        # Return the deserialized message. The first 2 bytes will be read as 
the
+        # amount of padding.
+        def deserialized_message(data)
+          # Read the first 2 bytes as the padding_bytes size
+          padding_bytes, = data.unpack('v')
+
+          # Slice out the serialized_data and deserialize it
+          serialized_data = data.slice(2 + padding_bytes, data.bytesize)
+          serializer.load serialized_data
+        end
+
+        def serializer
+          @serializer ||= @options[:serialize_json] ? JSON : Marshal
+        end
+      end
+
+      class V1
+        include Serializable
 
-        case opts[:pad_size]
-        when nil
+        # The secret String must be at least 64 bytes in size. The first 32 
bytes
+        # will be used for the encryption cipher key. The remainder will be 
used
+        # for an HMAC key.
+        #
+        # Options may include:
+        # * :serialize_json
+        #     Use JSON for message serialization instead of Marshal. This can 
be
+        #     viewed as a security enhancement.
+        # * :pad_size
+        #     Pad encrypted message data, to a multiple of this many bytes
+        #     (default: 32). This can be between 2-4096 bytes, or +nil+ to 
disable
+        #     padding.
+        # * :purpose
+        #     Limit messages to a specific purpose. This can be viewed as a
+        #     security enhancement to prevent message reuse from different 
contexts
+        #     if keys are reused.
+        #
+        # Cryptography and Output Format:
+        #
+        #   urlsafe_encode64(version + random_data + IV + encrypted data + 
HMAC)
+        #
+        #  Where:
+        #  * version - 1 byte with value 0x01
+        #  * random_data - 32 bytes used for generating the per-message secret
+        #  * IV - 16 bytes random initialization vector
+        #  * HMAC - 32 bytes HMAC-SHA-256 of all preceding data, plus the 
purpose
+        #    value
+        def initialize(secret, opts = {})
+          raise ArgumentError, 'secret must be a String' unless 
secret.is_a?(String)
+          raise ArgumentError, "invalid secret: #{secret.bytesize}, must be 
>=64" unless secret.bytesize >= 64
+
+          case opts[:pad_size]
+          when nil
           # padding is disabled
-        when Integer
-          raise ArgumentError, "invalid pad_size: #{opts[:pad_size]}" unless 
(2..4096).include? opts[:pad_size]
-        else
-          raise ArgumentError, "invalid pad_size: #{opts[:pad_size]}; must be 
Integer or nil"
+          when Integer
+            raise ArgumentError, "invalid pad_size: #{opts[:pad_size]}" unless 
(2..4096).include? opts[:pad_size]
+          else
+            raise ArgumentError, "invalid pad_size: #{opts[:pad_size]}; must 
be Integer or nil"
+          end
+
+          @options = {
+            serialize_json: false, pad_size: 32, purpose: nil
+          }.update(opts)
+
+          @hmac_secret = secret.dup.force_encoding(Encoding::BINARY)
+          @cipher_secret = @hmac_secret.slice!(0, 32)
+
+          @hmac_secret.freeze
+          @cipher_secret.freeze
         end
 
-        @options = {
-          serialize_json: false, pad_size: 32, purpose: nil
-        }.update(opts)
+        def decrypt(base64_data)
+          data = Base64.urlsafe_decode64(base64_data)
 
-        @hmac_secret = secret.dup.force_encoding('BINARY')
-        @cipher_secret = @hmac_secret.slice!(0, 32)
+          signature = data.slice!(-32..-1)
+          verify_authenticity!(data, signature)
 
-        @hmac_secret.freeze
-        @cipher_secret.freeze
-      end
+          version = data.slice!(0, 1)
+          raise InvalidMessage, 'wrong version' unless version == "\1"
 
-      def decrypt(base64_data)
-        data = Base64.urlsafe_decode64(base64_data)
+          message_secret = data.slice!(0, 32)
+          cipher_iv = data.slice!(0, 16)
 
-        signature = data.slice!(-32..-1)
+          cipher = new_cipher
+          cipher.decrypt
 
-        verify_authenticity! data, signature
+          set_cipher_key(cipher, 
cipher_secret_from_message_secret(message_secret))
 
-        # The version is reserved for future
-        _version = data.slice!(0, 1)
-        message_secret = data.slice!(0, 32)
-        cipher_iv = data.slice!(0, 16)
+          cipher.iv = cipher_iv
+          data = cipher.update(data) << cipher.final
 
-        cipher = new_cipher
-        cipher.decrypt
+          deserialized_message data
+        rescue ArgumentError
+          raise InvalidSignature, 'Message invalid'
+        end
 
-        set_cipher_key(cipher, 
cipher_secret_from_message_secret(message_secret))
+        def encrypt(message)
+          version = "\1"
 
-        cipher.iv = cipher_iv
-        data = cipher.update(data) << cipher.final
+          serialized_payload = serialize_payload(message)
+          message_secret, cipher_secret = new_message_and_cipher_secret
 
-        deserialized_message data
-      rescue ArgumentError
-        raise InvalidSignature, 'Message invalid'
-      end
+          cipher = new_cipher
+          cipher.encrypt
 
-      def encrypt(message)
-        version = "\1"
+          set_cipher_key(cipher, cipher_secret)
 
-        serialized_payload = serialize_payload(message)
-        message_secret, cipher_secret = new_message_and_cipher_secret
+          cipher_iv = cipher.random_iv
 
-        cipher = new_cipher
-        cipher.encrypt
+          encrypted_data = cipher.update(serialized_payload) << cipher.final
 
-        set_cipher_key(cipher, cipher_secret)
+          data = String.new
+          data << version
+          data << message_secret
+          data << cipher_iv
+          data << encrypted_data
+          data << compute_signature(data)
 
-        cipher_iv = cipher.random_iv
+          Base64.urlsafe_encode64(data)
+        end
 
-        encrypted_data = cipher.update(serialized_payload) << cipher.final
+        private
 
-        data = String.new
-        data << version
-        data << message_secret
-        data << cipher_iv
-        data << encrypted_data
-        data << compute_signature(data)
+        def new_cipher
+          OpenSSL::Cipher.new('aes-256-ctr')
+        end
 
-        Base64.urlsafe_encode64(data)
-      end
+        def new_message_and_cipher_secret
+          message_secret = SecureRandom.random_bytes(32)
 
-      private
+          [message_secret, cipher_secret_from_message_secret(message_secret)]
+        end
 
-      def new_cipher
-        OpenSSL::Cipher.new('aes-256-ctr')
-      end
+        def cipher_secret_from_message_secret(message_secret)
+          OpenSSL::HMAC.digest(OpenSSL::Digest.new('SHA256'), @cipher_secret, 
message_secret)
+        end
 
-      def new_message_and_cipher_secret
-        message_secret = SecureRandom.random_bytes(32)
+        def set_cipher_key(cipher, key)
+          cipher.key = key
+        end
 
-        [message_secret, cipher_secret_from_message_secret(message_secret)]
-      end
+        def compute_signature(data)
+          signing_data = data
+          signing_data += @options[:purpose] if @options[:purpose]
 
-      def cipher_secret_from_message_secret(message_secret)
-        OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, @cipher_secret, 
message_secret)
-      end
+          OpenSSL::HMAC.digest(OpenSSL::Digest.new('SHA256'), @hmac_secret, 
signing_data)
+        end
 
-      def set_cipher_key(cipher, key)
-        cipher.key = key
-      end
+        def verify_authenticity!(data, signature)
+          raise InvalidMessage, 'Message is invalid' if data.nil? || 
signature.nil?
 
-      def serializer
-        @serializer ||= @options[:serialize_json] ? JSON : Marshal
+          unless Rack::Utils.secure_compare(signature, compute_signature(data))
+            raise InvalidSignature, 'HMAC is invalid'
+          end
+        end
       end
 
-      def compute_signature(data)
-        signing_data = data
-        signing_data += @options[:purpose] if @options[:purpose]
+      class V2
+        include Serializable
+
+        # The secret String must be at least 32 bytes in size.
+        #
+        # Options may include:
+        # * :pad_size
+        #     Pad encrypted message data, to a multiple of this many bytes
+        #     (default: 32). This can be between 2-4096 bytes, or +nil+ to 
disable
+        #     padding.
+        # * :purpose
+        #     Limit messages to a specific purpose. This can be viewed as a
+        #     security enhancement to prevent message reuse from different 
contexts
+        #     if keys are reused.
+        #
+        # Cryptography and Output Format:
+        #
+        #   strict_encode64(version + salt + IV + authentication tag + 
ciphertext)
+        #
+        #  Where:
+        #  * version - 1 byte with value 0x02
+        #  * salt - 32 bytes used for generating the per-message secret
+        #  * IV - 12 bytes random initialization vector
+        #  * authentication tag - 16 bytes authentication tag generated by the 
GCM mode, covering version and salt
+        #
+        # Considerations about V2:
+        #
+        # 1) It uses non URL-safe Base64 encoding as it's faster than its
+        #    URL-safe counterpart - as of Ruby 3.2, Base64.urlsafe_encode64 is
+        #    roughly equivalent to
+        #
+        #    Base64.strict_encode64(data).tr("-_", "+/")
+        #
+        #    - and cookie values don't need to be URL-safe.
+        def initialize(secret, opts = {})
+          raise ArgumentError, 'secret must be a String' unless 
secret.is_a?(String)
+
+          unless secret.bytesize >= 32
+            raise ArgumentError, "invalid secret: it's #{secret.bytesize}-byte 
long, must be >=32"
+          end
 
-        OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, @hmac_secret, 
signing_data)
+          case opts[:pad_size]
+          when nil
+          # padding is disabled
+          when Integer
+            raise ArgumentError, "invalid pad_size: #{opts[:pad_size]}" unless 
(2..4096).include? opts[:pad_size]
+          else
+            raise ArgumentError, "invalid pad_size: #{opts[:pad_size]}; must 
be Integer or nil"
+          end
+
+          @options = {
+            serialize_json: false, pad_size: 32, purpose: nil
+          }.update(opts)
+
+          @cipher_secret = 
secret.dup.force_encoding(Encoding::BINARY).slice!(0, 32)
+          @cipher_secret.freeze
+        end
+
+        def decrypt(base64_data)
+          data = Base64.strict_decode64(base64_data)
+          if data.bytesize <= 61 # version + salt + iv + auth_tag = 61 byte 
(and we also need some ciphertext :)
+            raise InvalidMessage, 'invalid message'
+          end
+
+          version = data[0]
+          raise InvalidMessage, 'invalid message' unless version == "\2"
+
+          ciphertext = data.slice!(61..-1)
+          auth_tag = data.slice!(45, 16)
+          cipher_iv = data.slice!(33, 12)
+
+          cipher = new_cipher
+          cipher.decrypt
+          salt = data.slice(1, 32)
+          set_cipher_key(cipher, message_secret_from_salt(salt))
+          cipher.iv = cipher_iv
+          cipher.auth_tag = auth_tag
+          cipher.auth_data = (purpose = @options[:purpose]) ? data + purpose : 
data
+
+          plaintext = cipher.update(ciphertext) << cipher.final
+
+          deserialized_message plaintext
+        rescue ArgumentError, OpenSSL::Cipher::CipherError
+          raise InvalidSignature, 'invalid message'
+        end
+
+        def encrypt(message)
+          version = "\2"
+
+          serialized_payload = serialize_payload(message)
+
+          cipher = new_cipher
+          cipher.encrypt
+          salt, message_secret = new_salt_and_message_secret
+          set_cipher_key(cipher, message_secret)
+          cipher.iv_len = 12
+          cipher_iv = cipher.random_iv
+
+          data = String.new
+          data << version
+          data << salt
+
+          cipher.auth_data = (purpose = @options[:purpose]) ? data + purpose : 
data
+          encrypted_data = cipher.update(serialized_payload) << cipher.final
+
+          data << cipher_iv
+          data << auth_tag_from(cipher)
+          data << encrypted_data
+
+          Base64.strict_encode64(data)
+        end
+
+        private
+
+        def new_cipher
+          OpenSSL::Cipher.new('aes-256-gcm')
+        end
+
+        def new_salt_and_message_secret
+          salt = SecureRandom.random_bytes(32)
+
+          [salt, message_secret_from_salt(salt)]
+        end
+
+        def message_secret_from_salt(salt)
+          OpenSSL::HMAC.digest(OpenSSL::Digest.new('SHA256'), @cipher_secret, 
salt)
+        end
+
+        def set_cipher_key(cipher, key)
+          cipher.key = key
+        end
+
+        if RUBY_ENGINE == 'jruby'
+          # JRuby's OpenSSL implementation doesn't currently support passing
+          # an argument to #auth_tag. Here we work around that.
+          def auth_tag_from(cipher)
+            tag = cipher.auth_tag
+            raise Error, 'the auth tag must be 16 bytes long' if tag.bytesize 
!= 16
+
+            tag
+          end
+        else
+          def auth_tag_from(cipher)
+            cipher.auth_tag(16)
+          end
+        end
       end
 
-      def verify_authenticity!(data, signature)
-        raise InvalidMessage, 'Message is invalid' if data.nil? || 
signature.nil?
+      def initialize(secret, opts = {})
+        opts = opts.dup
 
-        unless Rack::Utils.secure_compare(signature, compute_signature(data))
-          raise InvalidSignature, 'HMAC is invalid'
+        @mode = opts.delete(:mode)&.to_sym || :guess_version
+        case @mode
+        when :v1
+          @v1 = V1.new(secret, opts)
+        when :v2
+          @v2 = V2.new(secret, opts)
+        else
+          @v1 = V1.new(secret, opts)
+          @v2 = V2.new(secret, opts)
         end
       end
 
-      # Returns a serialized payload of the message. If a :pad_size is 
supplied,
-      # the message will be padded. The first 2 bytes of the returned string 
will
-      # indicating the amount of padding.
-      def serialize_payload(message)
-        serialized_data = serializer.dump(message)
+      def decrypt(base64_data)
+        decryptor =
+          case @mode
+          when :v2
+            v2
+          when :v1
+            v1
+          else
+            guess_decryptor(base64_data)
+          end
 
-        return "#{[0].pack('v')}#{serialized_data}" if @options[:pad_size].nil?
+        decryptor.decrypt(base64_data)
+      end
 
-        padding_bytes = @options[:pad_size] - (2 + serialized_data.size) % 
@options[:pad_size]
-        padding_data = SecureRandom.random_bytes(padding_bytes)
+      def encrypt(message)
+        encryptor =
+          case @mode
+          when :v1
+            v1
+          else
+            v2
+          end
 
-        "#{[padding_bytes].pack('v')}#{padding_data}#{serialized_data}"
+        encryptor.encrypt(message)
       end
 
-      # Return the deserialized message. The first 2 bytes will be read as the
-      # amount of padding.
-      def deserialized_message(data)
-        # Read the first 2 bytes as the padding_bytes size
-        padding_bytes, = data.unpack('v')
+      private
+
+      attr_reader :v1, :v2
 
-        # Slice out the serialized_data and deserialize it
-        serialized_data = data.slice(2 + padding_bytes, data.bytesize)
-        serializer.load serialized_data
+      def guess_decryptor(base64_data)
+        raise InvalidMessage, 'invalid message' if base64_data.nil? || 
base64_data.bytesize < 4
+
+        first_encoded_4_bytes = base64_data.slice(0, 4)
+        # Transform the 4 bytes into non-URL-safe base64-encoded data. Nothing
+        # happens if the data is already non-URL-safe base64.
+        first_encoded_4_bytes.tr!('-_', '+/')
+        first_decoded_3_bytes = Base64.strict_decode64(first_encoded_4_bytes)
+
+        version = first_decoded_3_bytes[0]
+        case version
+        when "\2"
+          v2
+        when "\1"
+          v1
+        else
+          raise InvalidMessage, 'invalid message'
+        end
+      rescue ArgumentError
+        raise InvalidMessage, 'invalid message'
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/session/version.rb 
new/lib/rack/session/version.rb
--- old/lib/rack/session/version.rb     2025-05-06 12:54:56.000000000 +0200
+++ new/lib/rack/session/version.rb     1980-01-02 01:00:00.000000000 +0100
@@ -5,6 +5,6 @@
 
 module Rack
   module Session
-    VERSION = "2.1.1"
+    VERSION = "2.1.2"
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/session.rb new/lib/rack/session.rb
--- old/lib/rack/session.rb     2025-05-06 12:54:56.000000000 +0200
+++ new/lib/rack/session.rb     1980-01-02 01:00:00.000000000 +0100
@@ -8,6 +8,5 @@
   module Session
     autoload :Cookie, "rack/session/cookie"
     autoload :Pool, "rack/session/pool"
-    autoload :Memcache, "rack/session/memcache"
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2025-05-06 12:54:56.000000000 +0200
+++ new/metadata        1980-01-02 01:00:00.000000000 +0100
@@ -1,17 +1,16 @@
 --- !ruby/object:Gem::Specification
 name: rack-session
 version: !ruby/object:Gem::Version
-  version: 2.1.1
+  version: 2.1.2
 platform: ruby
 authors:
 - Samuel Williams
 - Jeremy Evans
 - Jon Dufresne
 - Philip Arndt
-autorequire:
 bindir: bin
 cert_chain: []
-date: 2025-05-06 00:00:00.000000000 Z
+date: 1980-01-02 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: base64
@@ -111,8 +110,6 @@
     - - ">="
       - !ruby/object:Gem::Version
         version: '0'
-description:
-email:
 executables: []
 extensions: []
 extra_rdoc_files: []
@@ -133,7 +130,6 @@
 - MIT
 metadata:
   rubygems_mfa_required: 'true'
-post_install_message:
 rdoc_options: []
 require_paths:
 - lib
@@ -148,8 +144,7 @@
     - !ruby/object:Gem::Version
       version: '0'
 requirements: []
-rubygems_version: 3.5.22
-signing_key:
+rubygems_version: 3.6.9
 specification_version: 4
 summary: A session implementation for Rack.
 test_files: []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/releases.md new/releases.md
--- old/releases.md     2025-05-06 12:54:56.000000000 +0200
+++ new/releases.md     1980-01-02 01:00:00.000000000 +0100
@@ -1,5 +1,9 @@
 # Releases
 
+## v2.1.2
+
+  - [CVE-2026-39324](https://github.com/advisories/GHSA-33qg-7wpp-89cq) Don't 
fall back to unencrypted coder if encryptors are present.
+
 ## v2.1.1
 
   - Prevent `Rack::Session::Pool` from recreating deleted sessions 
[CVE-2025-46336](https://github.com/rack/rack-session/security/advisories/GHSA-9j94-67jr-4cqj).

Reply via email to