activestorage 7.2.3 → 7.2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +94 -0
- data/app/controllers/active_storage/disk_controller.rb +4 -0
- data/app/controllers/concerns/active_storage/streaming.rb +8 -1
- data/app/models/active_storage/blob.rb +21 -0
- data/lib/active_storage/analyzer/image_analyzer/vips.rb +2 -0
- data/lib/active_storage/engine.rb +1 -0
- data/lib/active_storage/errors.rb +4 -0
- data/lib/active_storage/gem_version.rb +1 -1
- data/lib/active_storage/service/disk_service.rb +46 -2
- data/lib/active_storage/vips.rb +42 -0
- data/lib/active_storage.rb +14 -0
- metadata +14 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8d9ba18be252a1779cf9e9bb80dfdea0a23601c5e396c559285f0dac62a93d68
|
|
4
|
+
data.tar.gz: f2d0022eb4a41e9e22b94dee0acbfe65d8983b6c74408d3cd4480949064136d4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6a75369b13ef789b1b68cf8f6ec54b91b94f09208fae23c2df39d5bdf9c2f0f8f078fcea74013235d737ac4bfb618517618694f18f473bb2807612c623b44411
|
|
7
|
+
data.tar.gz: 2b9bdd8c74524d0669a42330326253a0d21f00a3a6ab560db46f68d3ef7824cb8e858a6ac225de29932ad3755af238708a7ddbbda8562e07764b4208d204e7d8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,97 @@
|
|
|
1
|
+
## Rails 7.2.3.2 (July 29, 2026) ##
|
|
2
|
+
|
|
3
|
+
* Disable libvips's unfuzzed image loaders and savers.
|
|
4
|
+
|
|
5
|
+
libvips flags some of its loaders and savers as "unfuzzed" or "untrusted", meaning they are only
|
|
6
|
+
safe for trusted content. Active Storage will call `Vips.block_untrusted(true)` to disable them
|
|
7
|
+
while booting. An application that needs a specific loader or saver may re-enable it in an
|
|
8
|
+
initializer.
|
|
9
|
+
|
|
10
|
+
This is a breaking change for applications that process image types with an unfuzzed loader or
|
|
11
|
+
saver. Variant transformation of BMP, ICO, and PSD attachments will raise `Vips::Error`, and
|
|
12
|
+
analysis of these and other types such as SVG, JPEG XL, JPEG 2000, and Netpbm will no longer
|
|
13
|
+
record `width` and `height`. Requesting an unfuzzed output format, typically FITS, JXL, or
|
|
14
|
+
anything delegated to ImageMagick, will also raise `Vips::Error`. Attaching, storing, and
|
|
15
|
+
downloading are unchanged.
|
|
16
|
+
|
|
17
|
+
An application seeing `Vips::Error` raised during image transformation may wish to remove the
|
|
18
|
+
affected content types from `config.active_storage.variable_content_types` in an initializer.
|
|
19
|
+
Active Storage will then treat those attachments as not variable and will not generate variants
|
|
20
|
+
for them. This most often matters to an application that transforms images during a request
|
|
21
|
+
rather than in a background job, where the failure surfaces as an error response instead of a
|
|
22
|
+
failed job.
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
Rails.application.config.active_storage.variable_content_types -=
|
|
26
|
+
%w[ image/bmp image/vnd.microsoft.icon image/vnd.adobe.photoshop ]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Applications using the `:mini_magick` variant processor will see no change in how their
|
|
30
|
+
attachments are processed, but the loaders and savers will be disabled process-wide whenever
|
|
31
|
+
ruby-vips is installed, and the version requirements below will still apply. Such an application
|
|
32
|
+
may remove ruby-vips from its Gemfile to avoid both.
|
|
33
|
+
|
|
34
|
+
The minimum supported version of libvips is now 8.13, and the minimum supported version of
|
|
35
|
+
ruby-vips is now 2.2.1. These are the earliest versions that are capable of disabling untrusted
|
|
36
|
+
operations. When ruby-vips is installed and either minimum is not met, Active Storage will raise
|
|
37
|
+
a `RuntimeError` while booting rather than run in an unsecurable environment.
|
|
38
|
+
|
|
39
|
+
[GHSA-xr9x-r78c-5hrm]
|
|
40
|
+
[CVE-2026-66066]
|
|
41
|
+
|
|
42
|
+
*Mike Dalessio*
|
|
43
|
+
|
|
44
|
+
## Rails 7.2.3.1 (March 23, 2026) ##
|
|
45
|
+
|
|
46
|
+
* Filter user supplied metadata in DirectUploadController
|
|
47
|
+
|
|
48
|
+
[CVE-2026-33173]
|
|
49
|
+
|
|
50
|
+
*Jean Boussier*
|
|
51
|
+
|
|
52
|
+
* Configurable maxmimum streaming chunk size
|
|
53
|
+
|
|
54
|
+
Makes sure that byte ranges for blobs don't exceed 100mb by default.
|
|
55
|
+
Content ranges that are too big can result in denial of service.
|
|
56
|
+
|
|
57
|
+
[CVE-2026-33174]
|
|
58
|
+
|
|
59
|
+
*Gannon McGibbon*
|
|
60
|
+
|
|
61
|
+
* Limit range requests to a single range
|
|
62
|
+
|
|
63
|
+
[CVE-2026-33658]
|
|
64
|
+
|
|
65
|
+
*Jean Boussier*
|
|
66
|
+
|
|
67
|
+
* Prevent path traversal in `DiskService`.
|
|
68
|
+
|
|
69
|
+
`DiskService#path_for` now raises an `InvalidKeyError` when passed keys with dot segments (".",
|
|
70
|
+
".."), or if the resolved path is outside the storage root directory.
|
|
71
|
+
|
|
72
|
+
`#path_for` also now consistently raises `InvalidKeyError` if the key is invalid in any way, for
|
|
73
|
+
example containing null bytes or having an incompatible encoding. Previously, the exception
|
|
74
|
+
raised may have been `ArgumentError` or `Encoding::CompatibilityError`.
|
|
75
|
+
|
|
76
|
+
`DiskController` now explicitly rescues `InvalidKeyError` with appropriate HTTP status codes.
|
|
77
|
+
|
|
78
|
+
[CVE-2026-33195]
|
|
79
|
+
|
|
80
|
+
*Mike Dalessio*
|
|
81
|
+
|
|
82
|
+
* Prevent glob injection in `DiskService#delete_prefixed`.
|
|
83
|
+
|
|
84
|
+
Escape glob metacharacters in the resolved path before passing to `Dir.glob`.
|
|
85
|
+
|
|
86
|
+
Note that this change breaks any existing code that is relying on `delete_prefixed` to expand
|
|
87
|
+
glob metacharacters. This change presumes that is unintended behavior (as other storage services
|
|
88
|
+
do not respect these metacharacters).
|
|
89
|
+
|
|
90
|
+
[CVE-2026-33202]
|
|
91
|
+
|
|
92
|
+
*Mike Dalessio*
|
|
93
|
+
|
|
94
|
+
|
|
1
95
|
## Rails 7.2.3 (October 28, 2025) ##
|
|
2
96
|
|
|
3
97
|
* Fix `config.active_storage.touch_attachment_records` to work with eager loading.
|
|
@@ -17,6 +17,8 @@ class ActiveStorage::DiskController < ActiveStorage::BaseController
|
|
|
17
17
|
end
|
|
18
18
|
rescue Errno::ENOENT
|
|
19
19
|
head :not_found
|
|
20
|
+
rescue ActiveStorage::InvalidKeyError
|
|
21
|
+
head :not_found
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
def update
|
|
@@ -32,6 +34,8 @@ class ActiveStorage::DiskController < ActiveStorage::BaseController
|
|
|
32
34
|
end
|
|
33
35
|
rescue ActiveStorage::IntegrityError
|
|
34
36
|
head ActionDispatch::Constants::UNPROCESSABLE_CONTENT
|
|
37
|
+
rescue ActiveStorage::InvalidKeyError
|
|
38
|
+
head ActionDispatch::Constants::UNPROCESSABLE_CONTENT
|
|
35
39
|
end
|
|
36
40
|
|
|
37
41
|
private
|
|
@@ -14,7 +14,8 @@ module ActiveStorage::Streaming
|
|
|
14
14
|
def send_blob_byte_range_data(blob, range_header, disposition: nil)
|
|
15
15
|
ranges = Rack::Utils.get_byte_ranges(range_header, blob.byte_size)
|
|
16
16
|
|
|
17
|
-
return head(:range_not_satisfiable)
|
|
17
|
+
return head(:range_not_satisfiable) unless ranges_valid?(ranges)
|
|
18
|
+
return head(:range_not_satisfiable) if ranges.length > ActiveStorage.streaming_max_ranges
|
|
18
19
|
|
|
19
20
|
if ranges.length == 1
|
|
20
21
|
range = ranges.first
|
|
@@ -51,6 +52,12 @@ module ActiveStorage::Streaming
|
|
|
51
52
|
)
|
|
52
53
|
end
|
|
53
54
|
|
|
55
|
+
def ranges_valid?(ranges)
|
|
56
|
+
return false if ranges.blank? || ranges.all?(&:blank?)
|
|
57
|
+
|
|
58
|
+
ranges.sum { |range| range.end - range.begin } < ActiveStorage.streaming_chunk_max_size
|
|
59
|
+
end
|
|
60
|
+
|
|
54
61
|
# Stream the blob from storage directly to the response. The disposition can be controlled by setting +disposition+.
|
|
55
62
|
# The content type and filename is set directly from the +blob+.
|
|
56
63
|
def send_blob_stream(blob, disposition: nil) # :doc:
|
|
@@ -16,10 +16,18 @@
|
|
|
16
16
|
# Blobs are intended to be immutable in as-so-far as their reference to a specific file goes. You're allowed to
|
|
17
17
|
# update a blob's metadata on a subsequent pass, but you should not update the key or change the uploaded file.
|
|
18
18
|
# If you need to create a derivative or otherwise change the blob, simply create a new blob and purge the old one.
|
|
19
|
+
#
|
|
20
|
+
# When using a custom +key+, the value is treated as trusted. Using untrusted user input
|
|
21
|
+
# as the key may result in unexpected behavior.
|
|
19
22
|
class ActiveStorage::Blob < ActiveStorage::Record
|
|
20
23
|
MINIMUM_TOKEN_LENGTH = 28
|
|
21
24
|
|
|
22
25
|
has_secure_token :key, length: MINIMUM_TOKEN_LENGTH
|
|
26
|
+
|
|
27
|
+
# FIXME: these property should never have been stored in the metadata.
|
|
28
|
+
# The blob table should be migrated to have dedicated columns for theses.
|
|
29
|
+
PROTECTED_METADATA = %w(analyzed identified composed)
|
|
30
|
+
private_constant :PROTECTED_METADATA
|
|
23
31
|
store :metadata, accessors: [ :analyzed, :identified, :composed ], coder: ActiveRecord::Coders::JSON
|
|
24
32
|
|
|
25
33
|
class_attribute :services, default: {}
|
|
@@ -93,6 +101,9 @@ class ActiveStorage::Blob < ActiveStorage::Record
|
|
|
93
101
|
# be saved before the upload begins to prevent the upload clobbering another due to key collisions.
|
|
94
102
|
# When providing a content type, pass <tt>identify: false</tt> to bypass
|
|
95
103
|
# automatic content type inference.
|
|
104
|
+
#
|
|
105
|
+
# The optional +key+ parameter is treated as trusted. Using untrusted user input
|
|
106
|
+
# as the key may result in unexpected behavior.
|
|
96
107
|
def create_and_upload!(key: nil, io:, filename:, content_type: nil, metadata: nil, service_name: nil, identify: true, record: nil)
|
|
97
108
|
create_after_unfurling!(key: key, io: io, filename: filename, content_type: content_type, metadata: metadata, service_name: service_name, identify: identify).tap do |blob|
|
|
98
109
|
blob.upload_without_unfurling(io)
|
|
@@ -105,6 +116,7 @@ class ActiveStorage::Blob < ActiveStorage::Record
|
|
|
105
116
|
# Once the form using the direct upload is submitted, the blob can be associated with the right record using
|
|
106
117
|
# the signed ID.
|
|
107
118
|
def create_before_direct_upload!(key: nil, filename:, byte_size:, checksum:, content_type: nil, metadata: nil, service_name: nil, record: nil)
|
|
119
|
+
metadata = filter_metadata(metadata)
|
|
108
120
|
create! key: key, filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type, metadata: metadata, service_name: service_name
|
|
109
121
|
end
|
|
110
122
|
|
|
@@ -152,6 +164,15 @@ class ActiveStorage::Blob < ActiveStorage::Record
|
|
|
152
164
|
combined_blob.save!
|
|
153
165
|
end
|
|
154
166
|
end
|
|
167
|
+
|
|
168
|
+
private
|
|
169
|
+
def filter_metadata(metadata)
|
|
170
|
+
if metadata.is_a?(Hash)
|
|
171
|
+
metadata.without(*PROTECTED_METADATA)
|
|
172
|
+
else
|
|
173
|
+
metadata
|
|
174
|
+
end
|
|
175
|
+
end
|
|
155
176
|
end
|
|
156
177
|
|
|
157
178
|
include Analyzable
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "active_storage/vips"
|
|
4
|
+
|
|
3
5
|
module ActiveStorage
|
|
4
6
|
# This analyzer relies on the third-party {ruby-vips}[https://github.com/libvips/ruby-vips] gem. Ruby-vips requires
|
|
5
7
|
# the {libvips}[https://libvips.github.io/libvips/] system library.
|
|
@@ -122,6 +122,7 @@ module ActiveStorage
|
|
|
122
122
|
ActiveStorage.binary_content_type = app.config.active_storage.binary_content_type || "application/octet-stream"
|
|
123
123
|
ActiveStorage.video_preview_arguments = app.config.active_storage.video_preview_arguments || "-y -vframes 1 -f image2"
|
|
124
124
|
ActiveStorage.track_variants = app.config.active_storage.track_variants || false
|
|
125
|
+
ActiveStorage.streaming_chunk_max_size = app.config.active_storage.streaming_chunk_max_size || 100.megabytes
|
|
125
126
|
end
|
|
126
127
|
end
|
|
127
128
|
|
|
@@ -26,4 +26,8 @@ module ActiveStorage
|
|
|
26
26
|
|
|
27
27
|
# Raised when a Previewer is unable to generate a preview image.
|
|
28
28
|
class PreviewError < Error; end
|
|
29
|
+
|
|
30
|
+
# Raised when a storage key resolves to a path outside the service's root
|
|
31
|
+
# directory, indicating a potential path traversal attack.
|
|
32
|
+
class InvalidKeyError < Error; end
|
|
29
33
|
end
|
|
@@ -60,7 +60,16 @@ module ActiveStorage
|
|
|
60
60
|
|
|
61
61
|
def delete_prefixed(prefix)
|
|
62
62
|
instrument :delete_prefixed, prefix: prefix do
|
|
63
|
-
|
|
63
|
+
prefix_path = path_for(prefix)
|
|
64
|
+
|
|
65
|
+
# File.expand_path (called within path_for) strips trailing slashes.
|
|
66
|
+
# Restore trailing separator if the original prefix had one, so that
|
|
67
|
+
# the glob "prefix/*" matches files inside the directory, not siblings
|
|
68
|
+
# whose names start with the prefix string.
|
|
69
|
+
prefix_path += "/" if prefix.end_with?("/")
|
|
70
|
+
|
|
71
|
+
escaped = escape_glob_metacharacters(prefix_path)
|
|
72
|
+
Dir.glob("#{escaped}*").each do |path|
|
|
64
73
|
FileUtils.rm_rf(path)
|
|
65
74
|
end
|
|
66
75
|
end
|
|
@@ -98,8 +107,39 @@ module ActiveStorage
|
|
|
98
107
|
{ "Content-Type" => content_type }
|
|
99
108
|
end
|
|
100
109
|
|
|
110
|
+
# Every filesystem operation in DiskService resolves paths through this method (or through
|
|
111
|
+
# make_path_for, which delegates here). This is the primary filesystem security check: all
|
|
112
|
+
# path-traversal protection is enforced here. New methods that touch the filesystem MUST use
|
|
113
|
+
# path_for or make_path_for -- never construct paths from +root+ directly.
|
|
101
114
|
def path_for(key) # :nodoc:
|
|
102
|
-
|
|
115
|
+
if key.blank?
|
|
116
|
+
raise ActiveStorage::InvalidKeyError, "key is blank"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Reject keys with dot segments as defense in depth. This prevents path traversal both outside
|
|
120
|
+
# and within the storage root. The root containment check below is a more fundamental check on
|
|
121
|
+
# path traversal outside of the disk service root.
|
|
122
|
+
begin
|
|
123
|
+
if key.split("/").intersect?(%w[. ..])
|
|
124
|
+
raise ActiveStorage::InvalidKeyError, "key has path traversal segments"
|
|
125
|
+
end
|
|
126
|
+
rescue Encoding::CompatibilityError
|
|
127
|
+
raise ActiveStorage::InvalidKeyError, "key has incompatible encoding"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
begin
|
|
131
|
+
path = File.expand_path(File.join(root, folder_for(key), key))
|
|
132
|
+
rescue ArgumentError
|
|
133
|
+
# ArgumentError catches null bytes
|
|
134
|
+
raise ActiveStorage::InvalidKeyError, "key is an invalid string"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# The resolved path must be inside the root directory.
|
|
138
|
+
unless path.start_with?(File.expand_path(root) + "/")
|
|
139
|
+
raise ActiveStorage::InvalidKeyError, "key is outside of disk service root"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
path
|
|
103
143
|
end
|
|
104
144
|
|
|
105
145
|
def compose(source_keys, destination_key, **)
|
|
@@ -156,6 +196,10 @@ module ActiveStorage
|
|
|
156
196
|
[ key[0..1], key[2..3] ].join("/")
|
|
157
197
|
end
|
|
158
198
|
|
|
199
|
+
def escape_glob_metacharacters(path)
|
|
200
|
+
path.gsub(/[\[\]*?{}\\]/) { |c| "\\#{c}" }
|
|
201
|
+
end
|
|
202
|
+
|
|
159
203
|
def make_path_for(key)
|
|
160
204
|
path_for(key).tap { |path| FileUtils.mkdir_p File.dirname(path) }
|
|
161
205
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_storage"
|
|
4
|
+
require "active_support/core_ext/string/filters"
|
|
5
|
+
|
|
6
|
+
begin
|
|
7
|
+
require "nokogiri"
|
|
8
|
+
rescue LoadError
|
|
9
|
+
# Ensure nokogiri is loaded before vips, which also depends on libxml2.
|
|
10
|
+
# See Nokogiri RFC: Stop exporting symbols:
|
|
11
|
+
# https://github.com/sparklemotion/nokogiri/discussions/2746
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
begin
|
|
15
|
+
gem "ruby-vips"
|
|
16
|
+
require "ruby-vips"
|
|
17
|
+
ActiveStorage::VIPS_AVAILABLE = true # :nodoc:
|
|
18
|
+
rescue LoadError => error
|
|
19
|
+
ActiveStorage::VIPS_AVAILABLE = false # :nodoc:
|
|
20
|
+
raise error unless error.message.match?(/libvips|ruby-vips/)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if ActiveStorage::VIPS_AVAILABLE
|
|
24
|
+
begin
|
|
25
|
+
# image_processing 2.0 calls Vips.block_untrusted(true) itself when it loads, so it has to load
|
|
26
|
+
# before the lines below. Leaving it to load later, when the transformer first asks for it,
|
|
27
|
+
# would disable the loaders again after an application's initializers had re-enabled them.
|
|
28
|
+
require "image_processing/vips"
|
|
29
|
+
rescue LoadError
|
|
30
|
+
# image_processing is only needed to generate variants, not to analyze blobs.
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
unless Vips.respond_to?(:block_untrusted)
|
|
34
|
+
raise <<~ERROR.squish
|
|
35
|
+
libvips's unfuzzed operations are not safe to use with untrusted content, and Active Storage
|
|
36
|
+
cannot disable them. Disabling them requires libvips 8.13 or later and ruby-vips 2.2.1 or
|
|
37
|
+
later. Please upgrade libvips and ruby-vips, or remove the ruby-vips gem from your Gemfile.
|
|
38
|
+
ERROR
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
Vips.block_untrusted(true)
|
|
42
|
+
end
|
data/lib/active_storage.rb
CHANGED
|
@@ -27,6 +27,7 @@ require "active_record"
|
|
|
27
27
|
require "active_support"
|
|
28
28
|
require "active_support/rails"
|
|
29
29
|
require "active_support/core_ext/numeric/time"
|
|
30
|
+
require "active_support/core_ext/numeric/bytes"
|
|
30
31
|
|
|
31
32
|
require "active_storage/version"
|
|
32
33
|
require "active_storage/deprecator"
|
|
@@ -350,6 +351,7 @@ module ActiveStorage
|
|
|
350
351
|
]
|
|
351
352
|
mattr_accessor :unsupported_image_processing_arguments
|
|
352
353
|
|
|
354
|
+
mattr_accessor :streaming_chunk_max_size, default: 100.megabytes
|
|
353
355
|
mattr_accessor :service_urls_expire_in, default: 5.minutes
|
|
354
356
|
mattr_accessor :touch_attachment_records, default: true
|
|
355
357
|
mattr_accessor :urls_expire_in
|
|
@@ -360,6 +362,18 @@ module ActiveStorage
|
|
|
360
362
|
|
|
361
363
|
mattr_accessor :track_variants, default: false
|
|
362
364
|
|
|
365
|
+
singleton_class.attr_accessor :checksum_implementation
|
|
366
|
+
@checksum_implementation = OpenSSL::Digest::MD5
|
|
367
|
+
begin
|
|
368
|
+
@checksum_implementation.hexdigest("test")
|
|
369
|
+
rescue # OpenSSL may have MD5 disabled
|
|
370
|
+
require "digest/md5"
|
|
371
|
+
@checksum_implementation = Digest::MD5
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
singleton_class.attr_accessor :streaming_max_ranges
|
|
375
|
+
@streaming_max_ranges = 1
|
|
376
|
+
|
|
363
377
|
mattr_accessor :video_preview_arguments, default: "-y -vframes 1 -f image2"
|
|
364
378
|
|
|
365
379
|
module Transformers
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activestorage
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 7.2.3
|
|
4
|
+
version: 7.2.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Heinemeier Hansson
|
|
@@ -15,56 +15,56 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 7.2.3
|
|
18
|
+
version: 7.2.3.2
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 7.2.3
|
|
25
|
+
version: 7.2.3.2
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: actionpack
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - '='
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 7.2.3
|
|
32
|
+
version: 7.2.3.2
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - '='
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 7.2.3
|
|
39
|
+
version: 7.2.3.2
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: activejob
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
44
|
- - '='
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 7.2.3
|
|
46
|
+
version: 7.2.3.2
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - '='
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 7.2.3
|
|
53
|
+
version: 7.2.3.2
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: activerecord
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - '='
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: 7.2.3
|
|
60
|
+
version: 7.2.3.2
|
|
61
61
|
type: :runtime
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
65
|
- - '='
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: 7.2.3
|
|
67
|
+
version: 7.2.3.2
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
69
|
name: marcel
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -183,16 +183,17 @@ files:
|
|
|
183
183
|
- lib/active_storage/transformers/image_processing_transformer.rb
|
|
184
184
|
- lib/active_storage/transformers/transformer.rb
|
|
185
185
|
- lib/active_storage/version.rb
|
|
186
|
+
- lib/active_storage/vips.rb
|
|
186
187
|
- lib/tasks/activestorage.rake
|
|
187
188
|
homepage: https://rubyonrails.org
|
|
188
189
|
licenses:
|
|
189
190
|
- MIT
|
|
190
191
|
metadata:
|
|
191
192
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
|
192
|
-
changelog_uri: https://github.com/rails/rails/blob/v7.2.3/activestorage/CHANGELOG.md
|
|
193
|
-
documentation_uri: https://api.rubyonrails.org/v7.2.3/
|
|
193
|
+
changelog_uri: https://github.com/rails/rails/blob/v7.2.3.2/activestorage/CHANGELOG.md
|
|
194
|
+
documentation_uri: https://api.rubyonrails.org/v7.2.3.2/
|
|
194
195
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
|
195
|
-
source_code_uri: https://github.com/rails/rails/tree/v7.2.3/activestorage
|
|
196
|
+
source_code_uri: https://github.com/rails/rails/tree/v7.2.3.2/activestorage
|
|
196
197
|
rubygems_mfa_required: 'true'
|
|
197
198
|
rdoc_options: []
|
|
198
199
|
require_paths:
|
|
@@ -208,7 +209,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
208
209
|
- !ruby/object:Gem::Version
|
|
209
210
|
version: '0'
|
|
210
211
|
requirements: []
|
|
211
|
-
rubygems_version:
|
|
212
|
+
rubygems_version: 4.0.16
|
|
212
213
|
specification_version: 4
|
|
213
214
|
summary: Local and cloud file storage framework.
|
|
214
215
|
test_files: []
|