Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rubygem-activestorage-8.0 for 
openSUSE:Factory checked in at 2026-07-07 21:05:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-activestorage-8.0 (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-activestorage-8.0.new.1982 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-activestorage-8.0"

Tue Jul  7 21:05:05 2026 rev:6 rq:1364225 version:8.0.5

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/rubygem-activestorage-8.0/rubygem-activestorage-8.0.changes
      2025-10-10 17:13:51.732638133 +0200
+++ 
/work/SRC/openSUSE:Factory/.rubygem-activestorage-8.0.new.1982/rubygem-activestorage-8.0.changes
    2026-07-07 21:07:50.319916306 +0200
@@ -1,0 +2,6 @@
+Tue Jul  7 09:05:53 UTC 2026 - Aleksei Burlakov <[email protected]>
+
+- Update to version 8.0.5:
+  
https://rubyonrails.org/2026/3/24/Rails-Versions-8-0-5-and-8-1-3-have-been-released
 
+
+-------------------------------------------------------------------

Old:
----
  activestorage-8.0.3.gem

New:
----
  activestorage-8.0.5.gem

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

Other differences:
------------------
++++++ rubygem-activestorage-8.0.spec ++++++
--- /var/tmp/diff_new_pack.0Fj9RN/_old  2026-07-07 21:07:50.863935067 +0200
+++ /var/tmp/diff_new_pack.0Fj9RN/_new  2026-07-07 21:07:50.867935205 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-activestorage-8.0
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# 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-activestorage-8.0
-Version:        8.0.3
+Version:        8.0.5
 Release:        0
 %define mod_name activestorage
 %define mod_full_name %{mod_name}-%{version}

++++++ activestorage-8.0.3.gem -> activestorage-8.0.5.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md
--- old/CHANGELOG.md    1980-01-02 01:00:00.000000000 +0100
+++ new/CHANGELOG.md    1980-01-02 01:00:00.000000000 +0100
@@ -1,3 +1,66 @@
+## Rails 8.0.5 (March 24, 2026) ##
+
+*   Fix `ActiveStorage::Blob` content type predicate methods to handle `nil`.
+
+    *Daichi KUDO*
+
+
+## Rails 8.0.4.1 (March 23, 2026) ##
+
+*   Filter user supplied metadata in DirectUploadController
+
+    [CVE-2026-33173]
+
+    *Jean Boussier*
+
+*   Configurable maxmimum streaming chunk size
+
+    Makes sure that byte ranges for blobs don't exceed 100mb by default.
+    Content ranges that are too big can result in denial of service.
+
+    [CVE-2026-33174]
+
+    *Gannon McGibbon*
+
+*   Limit range requests to a single range
+
+    [CVE-2026-33658]
+
+    *Jean Boussier*
+
+*   Prevent path traversal in `DiskService`.
+
+    `DiskService#path_for` now raises an `InvalidKeyError` when passed keys 
with dot segments (".",
+    ".."), or if the resolved path is outside the storage root directory.
+
+    `#path_for` also now consistently raises `InvalidKeyError` if the key is 
invalid in any way, for
+    example containing null bytes or having an incompatible encoding. 
Previously, the exception
+    raised may have been `ArgumentError` or `Encoding::CompatibilityError`.
+
+    `DiskController` now explicitly rescues `InvalidKeyError` with appropriate 
HTTP status codes.
+
+    [CVE-2026-33195]
+
+    *Mike Dalessio*
+
+*   Prevent glob injection in `DiskService#delete_prefixed`.
+
+    Escape glob metacharacters in the resolved path before passing to 
`Dir.glob`.
+
+    Note that this change breaks any existing code that is relying on 
`delete_prefixed` to expand
+    glob metacharacters. This change presumes that is unintended behavior (as 
other storage services
+    do not respect these metacharacters).
+
+    [CVE-2026-33202]
+
+    *Mike Dalessio*
+
+
+## Rails 8.0.4 (October 28, 2025) ##
+
+*   No changes.
+
+
 ## Rails 8.0.3 (September 22, 2025) ##
 
 *   Address deprecation of `Aws::S3::Object#upload_stream` in 
`ActiveStorage::Service::S3Service`.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/app/controllers/active_storage/disk_controller.rb 
new/app/controllers/active_storage/disk_controller.rb
--- old/app/controllers/active_storage/disk_controller.rb       1980-01-02 
01:00:00.000000000 +0100
+++ new/app/controllers/active_storage/disk_controller.rb       1980-01-02 
01:00:00.000000000 +0100
@@ -17,6 +17,8 @@
     end
   rescue Errno::ENOENT
     head :not_found
+  rescue ActiveStorage::InvalidKeyError
+    head :not_found
   end
 
   def update
@@ -32,6 +34,8 @@
     end
   rescue ActiveStorage::IntegrityError
     head ActionDispatch::Constants::UNPROCESSABLE_CONTENT
+  rescue ActiveStorage::InvalidKeyError
+    head ActionDispatch::Constants::UNPROCESSABLE_CONTENT
   end
 
   private
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/app/controllers/concerns/active_storage/streaming.rb 
new/app/controllers/concerns/active_storage/streaming.rb
--- old/app/controllers/concerns/active_storage/streaming.rb    1980-01-02 
01:00:00.000000000 +0100
+++ new/app/controllers/concerns/active_storage/streaming.rb    1980-01-02 
01:00:00.000000000 +0100
@@ -14,7 +14,8 @@
     def send_blob_byte_range_data(blob, range_header, disposition: nil)
       ranges = Rack::Utils.get_byte_ranges(range_header, blob.byte_size)
 
-      return head(:range_not_satisfiable) if ranges.blank? || 
ranges.all?(&:blank?)
+      return head(:range_not_satisfiable) unless ranges_valid?(ranges)
+      return head(:range_not_satisfiable) if ranges.length > 
ActiveStorage.streaming_max_ranges
 
       if ranges.length == 1
         range = ranges.first
@@ -51,6 +52,12 @@
       )
     end
 
+    def ranges_valid?(ranges)
+      return false if ranges.blank? || ranges.all?(&:blank?)
+
+      ranges.sum { |range| range.end - range.begin } < 
ActiveStorage.streaming_chunk_max_size
+    end
+
     # Stream the blob from storage directly to the response. The disposition 
can be controlled by setting +disposition+.
     # The content type and filename is set directly from the +blob+.
     def send_blob_stream(blob, disposition: nil) # :doc:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/app/models/active_storage/blob.rb 
new/app/models/active_storage/blob.rb
--- old/app/models/active_storage/blob.rb       1980-01-02 01:00:00.000000000 
+0100
+++ new/app/models/active_storage/blob.rb       1980-01-02 01:00:00.000000000 
+0100
@@ -16,10 +16,18 @@
 # Blobs are intended to be immutable in as-so-far as their reference to a 
specific file goes. You're allowed to
 # update a blob's metadata on a subsequent pass, but you should not update the 
key or change the uploaded file.
 # If you need to create a derivative or otherwise change the blob, simply 
create a new blob and purge the old one.
+#
+# When using a custom +key+, the value is treated as trusted. Using untrusted 
user input
+# as the key may result in unexpected behavior.
 class ActiveStorage::Blob < ActiveStorage::Record
   MINIMUM_TOKEN_LENGTH = 28
 
   has_secure_token :key, length: MINIMUM_TOKEN_LENGTH
+
+  # FIXME: these property should never have been stored in the metadata.
+  # The blob table should be migrated to have dedicated columns for theses.
+  PROTECTED_METADATA = %w(analyzed identified composed)
+  private_constant :PROTECTED_METADATA
   store :metadata, accessors: [ :analyzed, :identified, :composed ], coder: 
ActiveRecord::Coders::JSON
 
   class_attribute :services, default: {}
@@ -92,6 +100,9 @@
     # be saved before the upload begins to prevent the upload clobbering 
another due to key collisions.
     # When providing a content type, pass <tt>identify: false</tt> to bypass
     # automatic content type inference.
+    #
+    # The optional +key+ parameter is treated as trusted. Using untrusted user 
input
+    # as the key may result in unexpected behavior.
     def create_and_upload!(key: nil, io:, filename:, content_type: nil, 
metadata: nil, service_name: nil, identify: true, record: nil)
       create_after_unfurling!(key: key, io: io, filename: filename, 
content_type: content_type, metadata: metadata, service_name: service_name, 
identify: identify).tap do |blob|
         blob.upload_without_unfurling(io)
@@ -104,6 +115,7 @@
     # Once the form using the direct upload is submitted, the blob can be 
associated with the right record using
     # the signed ID.
     def create_before_direct_upload!(key: nil, filename:, byte_size:, 
checksum:, content_type: nil, metadata: nil, service_name: nil, record: nil)
+      metadata = filter_metadata(metadata)
       create! key: key, filename: filename, byte_size: byte_size, checksum: 
checksum, content_type: content_type, metadata: metadata, service_name: 
service_name
     end
 
@@ -151,6 +163,15 @@
         combined_blob.save!
       end
     end
+
+    private
+      def filter_metadata(metadata)
+        if metadata.is_a?(Hash)
+          metadata.without(*PROTECTED_METADATA)
+        else
+          metadata
+        end
+      end
   end
 
   include Analyzable
@@ -189,22 +210,22 @@
 
   # Returns true if the content_type of this blob is in the image range, like 
image/png.
   def image?
-    content_type.start_with?("image")
+    content_type&.start_with?("image")
   end
 
   # Returns true if the content_type of this blob is in the audio range, like 
audio/mpeg.
   def audio?
-    content_type.start_with?("audio")
+    content_type&.start_with?("audio")
   end
 
   # Returns true if the content_type of this blob is in the video range, like 
video/mp4.
   def video?
-    content_type.start_with?("video")
+    content_type&.start_with?("video")
   end
 
   # Returns true if the content_type of this blob is in the text range, like 
text/plain.
   def text?
-    content_type.start_with?("text")
+    content_type&.start_with?("text")
   end
 
   # Returns the URL of the blob on the service. This returns a permanent URL 
for public files, and returns a
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/active_storage/engine.rb 
new/lib/active_storage/engine.rb
--- old/lib/active_storage/engine.rb    1980-01-02 01:00:00.000000000 +0100
+++ new/lib/active_storage/engine.rb    1980-01-02 01:00:00.000000000 +0100
@@ -122,6 +122,7 @@
         ActiveStorage.binary_content_type = 
app.config.active_storage.binary_content_type || "application/octet-stream"
         ActiveStorage.video_preview_arguments = 
app.config.active_storage.video_preview_arguments || "-y -vframes 1 -f image2"
         ActiveStorage.track_variants = 
app.config.active_storage.track_variants || false
+        ActiveStorage.streaming_chunk_max_size = 
app.config.active_storage.streaming_chunk_max_size || 100.megabytes
       end
     end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/active_storage/errors.rb 
new/lib/active_storage/errors.rb
--- old/lib/active_storage/errors.rb    1980-01-02 01:00:00.000000000 +0100
+++ new/lib/active_storage/errors.rb    1980-01-02 01:00:00.000000000 +0100
@@ -26,4 +26,8 @@
 
   # Raised when a Previewer is unable to generate a preview image.
   class PreviewError < Error; end
+
+  # Raised when a storage key resolves to a path outside the service's root
+  # directory, indicating a potential path traversal attack.
+  class InvalidKeyError < Error; end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/active_storage/gem_version.rb 
new/lib/active_storage/gem_version.rb
--- old/lib/active_storage/gem_version.rb       1980-01-02 01:00:00.000000000 
+0100
+++ new/lib/active_storage/gem_version.rb       1980-01-02 01:00:00.000000000 
+0100
@@ -9,7 +9,7 @@
   module VERSION
     MAJOR = 8
     MINOR = 0
-    TINY  = 3
+    TINY  = 5
     PRE   = nil
 
     STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/active_storage/service/disk_service.rb 
new/lib/active_storage/service/disk_service.rb
--- old/lib/active_storage/service/disk_service.rb      1980-01-02 
01:00:00.000000000 +0100
+++ new/lib/active_storage/service/disk_service.rb      1980-01-02 
01:00:00.000000000 +0100
@@ -60,7 +60,16 @@
 
     def delete_prefixed(prefix)
       instrument :delete_prefixed, prefix: prefix do
-        Dir.glob(path_for("#{prefix}*")).each do |path|
+        prefix_path = path_for(prefix)
+
+        # File.expand_path (called within path_for) strips trailing slashes.
+        # Restore trailing separator if the original prefix had one, so that
+        # the glob "prefix/*" matches files inside the directory, not siblings
+        # whose names start with the prefix string.
+        prefix_path += "/" if prefix.end_with?("/")
+
+        escaped = escape_glob_metacharacters(prefix_path)
+        Dir.glob("#{escaped}*").each do |path|
           FileUtils.rm_rf(path)
         end
       end
@@ -98,8 +107,39 @@
       { "Content-Type" => content_type }
     end
 
+    # Every filesystem operation in DiskService resolves paths through this 
method (or through
+    # make_path_for, which delegates here). This is the primary filesystem 
security check: all
+    # path-traversal protection is enforced here. New methods that touch the 
filesystem MUST use
+    # path_for or make_path_for -- never construct paths from +root+ directly.
     def path_for(key) # :nodoc:
-      File.join root, folder_for(key), key
+      if key.blank?
+        raise ActiveStorage::InvalidKeyError, "key is blank"
+      end
+
+      # Reject keys with dot segments as defense in depth. This prevents path 
traversal both outside
+      # and within the storage root. The root containment check below is a 
more fundamental check on
+      # path traversal outside of the disk service root.
+      begin
+        if key.split("/").intersect?(%w[. ..])
+          raise ActiveStorage::InvalidKeyError, "key has path traversal 
segments"
+        end
+      rescue Encoding::CompatibilityError
+        raise ActiveStorage::InvalidKeyError, "key has incompatible encoding"
+      end
+
+      begin
+        path = File.expand_path(File.join(root, folder_for(key), key))
+      rescue ArgumentError
+        # ArgumentError catches null bytes
+        raise ActiveStorage::InvalidKeyError, "key is an invalid string"
+      end
+
+      # The resolved path must be inside the root directory.
+      unless path.start_with?(File.expand_path(root) + "/")
+        raise ActiveStorage::InvalidKeyError, "key is outside of disk service 
root"
+      end
+
+      path
     end
 
     def compose(source_keys, destination_key, **)
@@ -156,6 +196,10 @@
         [ key[0..1], key[2..3] ].join("/")
       end
 
+      def escape_glob_metacharacters(path)
+        path.gsub(/[\[\]*?{}\\]/) { |c| "\\#{c}" }
+      end
+
       def make_path_for(key)
         path_for(key).tap { |path| FileUtils.mkdir_p File.dirname(path) }
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/active_storage.rb new/lib/active_storage.rb
--- old/lib/active_storage.rb   1980-01-02 01:00:00.000000000 +0100
+++ new/lib/active_storage.rb   1980-01-02 01:00:00.000000000 +0100
@@ -27,6 +27,7 @@
 require "active_support"
 require "active_support/rails"
 require "active_support/core_ext/numeric/time"
+require "active_support/core_ext/numeric/bytes"
 
 require "active_storage/version"
 require "active_storage/deprecator"
@@ -350,6 +351,7 @@
   ]
   mattr_accessor :unsupported_image_processing_arguments
 
+  mattr_accessor :streaming_chunk_max_size, default: 100.megabytes
   mattr_accessor :service_urls_expire_in, default: 5.minutes
   mattr_accessor :touch_attachment_records, default: true
   mattr_accessor :urls_expire_in
@@ -360,6 +362,18 @@
 
   mattr_accessor :track_variants, default: false
 
+  singleton_class.attr_accessor :checksum_implementation
+  @checksum_implementation = OpenSSL::Digest::MD5
+  begin
+    @checksum_implementation.hexdigest("test")
+  rescue # OpenSSL may have MD5 disabled
+    require "digest/md5"
+    @checksum_implementation = Digest::MD5
+  end
+
+  singleton_class.attr_accessor :streaming_max_ranges
+  @streaming_max_ranges = 1
+
   mattr_accessor :video_preview_arguments, default: "-y -vframes 1 -f image2"
 
   module Transformers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        1980-01-02 01:00:00.000000000 +0100
+++ new/metadata        1980-01-02 01:00:00.000000000 +0100
@@ -1,7 +1,7 @@
 --- !ruby/object:Gem::Specification
 name: activestorage
 version: !ruby/object:Gem::Version
-  version: 8.0.3
+  version: 8.0.5
 platform: ruby
 authors:
 - David Heinemeier Hansson
@@ -15,56 +15,56 @@
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 8.0.3
+        version: 8.0.5
   type: :runtime
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 8.0.3
+        version: 8.0.5
 - !ruby/object:Gem::Dependency
   name: actionpack
   requirement: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 8.0.3
+        version: 8.0.5
   type: :runtime
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 8.0.3
+        version: 8.0.5
 - !ruby/object:Gem::Dependency
   name: activejob
   requirement: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 8.0.3
+        version: 8.0.5
   type: :runtime
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 8.0.3
+        version: 8.0.5
 - !ruby/object:Gem::Dependency
   name: activerecord
   requirement: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 8.0.3
+        version: 8.0.5
   type: :runtime
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 8.0.3
+        version: 8.0.5
 - !ruby/object:Gem::Dependency
   name: marcel
   requirement: !ruby/object:Gem::Requirement
@@ -189,10 +189,10 @@
 - MIT
 metadata:
   bug_tracker_uri: https://github.com/rails/rails/issues
-  changelog_uri: 
https://github.com/rails/rails/blob/v8.0.3/activestorage/CHANGELOG.md
-  documentation_uri: https://api.rubyonrails.org/v8.0.3/
+  changelog_uri: 
https://github.com/rails/rails/blob/v8.0.5/activestorage/CHANGELOG.md
+  documentation_uri: https://api.rubyonrails.org/v8.0.5/
   mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
-  source_code_uri: https://github.com/rails/rails/tree/v8.0.3/activestorage
+  source_code_uri: https://github.com/rails/rails/tree/v8.0.5/activestorage
   rubygems_mfa_required: 'true'
 rdoc_options: []
 require_paths:
@@ -208,7 +208,7 @@
     - !ruby/object:Gem::Version
       version: '0'
 requirements: []
-rubygems_version: 3.6.9
+rubygems_version: 4.0.6
 specification_version: 4
 summary: Local and cloud file storage framework.
 test_files: []

Reply via email to