carrierwave 1.3.1 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of carrierwave might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +3 -0
- data/lib/carrierwave/mounter.rb +1 -1
- data/lib/carrierwave/processing/rmagick.rb +9 -3
- data/lib/carrierwave/sanitized_file.rb +6 -7
- data/lib/carrierwave/storage/fog.rb +3 -5
- data/lib/carrierwave/uploader/download.rb +59 -16
- data/lib/carrierwave/version.rb +1 -1
- metadata +39 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ef69bd6c6815eeb01f996a2506ac01cc6f366a566217fc366dde5a0653f92a1
|
4
|
+
data.tar.gz: 396d34e7c58d946ada4ede908f672c1abec0e4d59031dfca7455ee0d77d7d2db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2ed581457edf26ff5c60922f98bed68b3f539196f15ff38f780be5619cc5aec21481be0dd78f6c16e8ab3fa1a83b6e2d859030c723bc357dd78a3d0352a410b
|
7
|
+
data.tar.gz: 897d714945716a4bdcf48036c194212d9724863392931bde86bc2a44a2743c3088962ef1b633417262239e2ef8c374694afc634ac8e5074c2ff7d767a313bcbe
|
data/README.md
CHANGED
@@ -163,6 +163,9 @@ class User < ActiveRecord::Base
|
|
163
163
|
end
|
164
164
|
```
|
165
165
|
|
166
|
+
Make sure that you mount the uploader with write (mount_uploaders) with `s` not (mount_uploader)
|
167
|
+
in order to avoid errors when uploading multiple files
|
168
|
+
|
166
169
|
Make sure your file input fields are set up as multiple file fields. For
|
167
170
|
example in Rails you'll want to do something like this:
|
168
171
|
|
data/lib/carrierwave/mounter.rb
CHANGED
@@ -378,9 +378,15 @@ module CarrierWave
|
|
378
378
|
|
379
379
|
def create_info_block(options)
|
380
380
|
return nil unless options
|
381
|
-
|
382
|
-
|
383
|
-
|
381
|
+
proc do |img|
|
382
|
+
options.each do |k, v|
|
383
|
+
if v.is_a?(String) && (matches = v.match(/^["'](.+)["']/))
|
384
|
+
ActiveSupport::Deprecation.warn "Passing quoted strings like #{v} to #manipulate! is deprecated, pass them without quoting."
|
385
|
+
v = matches[1]
|
386
|
+
end
|
387
|
+
img.public_send(:"#{k}=", v)
|
388
|
+
end
|
389
|
+
end
|
384
390
|
end
|
385
391
|
|
386
392
|
def destroy_image(image)
|
@@ -114,12 +114,11 @@ module CarrierWave
|
|
114
114
|
# [String, nil] the path where the file is located.
|
115
115
|
#
|
116
116
|
def path
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
end
|
117
|
+
return if @file.blank?
|
118
|
+
if is_path?
|
119
|
+
File.expand_path(@file)
|
120
|
+
elsif @file.respond_to?(:path) && !@file.path.blank?
|
121
|
+
File.expand_path(@file.path)
|
123
122
|
end
|
124
123
|
end
|
125
124
|
|
@@ -313,7 +312,7 @@ module CarrierWave
|
|
313
312
|
def mkdir!(path, directory_permissions)
|
314
313
|
options = {}
|
315
314
|
options[:mode] = directory_permissions if directory_permissions
|
316
|
-
FileUtils.mkdir_p(File.dirname(path), options) unless File.exist?(File.dirname(path))
|
315
|
+
FileUtils.mkdir_p(File.dirname(path), **options) unless File.exist?(File.dirname(path))
|
317
316
|
end
|
318
317
|
|
319
318
|
def chmod!(path, permissions)
|
@@ -177,7 +177,7 @@ module CarrierWave
|
|
177
177
|
|
178
178
|
##
|
179
179
|
# Return a temporary authenticated url to a private file, if available
|
180
|
-
# Only supported for AWS, Rackspace and
|
180
|
+
# Only supported for AWS, Rackspace, Google and AzureRM providers
|
181
181
|
#
|
182
182
|
# === Returns
|
183
183
|
#
|
@@ -186,7 +186,7 @@ module CarrierWave
|
|
186
186
|
# [NilClass] no authenticated url available
|
187
187
|
#
|
188
188
|
def authenticated_url(options = {})
|
189
|
-
if ['AWS', 'Google', 'Rackspace', 'OpenStack'].include?(@uploader.fog_credentials[:provider])
|
189
|
+
if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM'].include?(@uploader.fog_credentials[:provider])
|
190
190
|
# avoid a get by using local references
|
191
191
|
local_directory = connection.directories.new(:key => @uploader.fog_directory)
|
192
192
|
local_file = local_directory.files.new(:key => path)
|
@@ -200,10 +200,8 @@ module CarrierWave
|
|
200
200
|
warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
|
201
201
|
local_file.url(expire_at)
|
202
202
|
end
|
203
|
-
when 'Rackspace'
|
203
|
+
when 'Rackspace', 'OpenStack'
|
204
204
|
connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
|
205
|
-
when 'OpenStack'
|
206
|
-
connection.get_object_https_url(@uploader.fog_directory, path, expire_at)
|
207
205
|
else
|
208
206
|
local_file.url(expire_at)
|
209
207
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'open-uri'
|
2
|
+
require 'ssrf_filter'
|
2
3
|
|
3
4
|
module CarrierWave
|
4
5
|
module Uploader
|
@@ -10,15 +11,18 @@ module CarrierWave
|
|
10
11
|
include CarrierWave::Uploader::Cache
|
11
12
|
|
12
13
|
class RemoteFile
|
13
|
-
|
14
|
+
attr_reader :uri
|
15
|
+
|
16
|
+
def initialize(uri, remote_headers = {}, skip_ssrf_protection: false)
|
14
17
|
@uri = uri
|
15
|
-
@remote_headers = remote_headers
|
16
|
-
@file = nil
|
18
|
+
@remote_headers = remote_headers.reverse_merge('User-Agent' => "CarrierWave/#{CarrierWave::VERSION}")
|
19
|
+
@file, @content_type, @headers = nil
|
20
|
+
@skip_ssrf_protection = skip_ssrf_protection
|
17
21
|
end
|
18
22
|
|
19
23
|
def original_filename
|
20
24
|
filename = filename_from_header || filename_from_uri
|
21
|
-
mime_type = MIME::Types[
|
25
|
+
mime_type = MIME::Types[content_type].first
|
22
26
|
unless File.extname(filename).present? || mime_type.blank?
|
23
27
|
filename = "#{filename}.#{mime_type.extensions.first}"
|
24
28
|
end
|
@@ -33,15 +37,35 @@ module CarrierWave
|
|
33
37
|
@uri.scheme =~ /^https?$/
|
34
38
|
end
|
35
39
|
|
36
|
-
|
40
|
+
def content_type
|
41
|
+
@content_type || 'application/octet-stream'
|
42
|
+
end
|
43
|
+
|
44
|
+
def headers
|
45
|
+
@headers || {}
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
37
49
|
|
38
50
|
def file
|
39
51
|
if @file.blank?
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
52
|
+
if @skip_ssrf_protection
|
53
|
+
@file = (URI.respond_to?(:open) ? URI : Kernel).open(@uri.to_s, @remote_headers)
|
54
|
+
@file = @file.is_a?(String) ? StringIO.new(@file) : @file
|
55
|
+
@content_type = @file.content_type
|
56
|
+
@headers = @file.meta
|
57
|
+
@uri = @file.base_uri
|
58
|
+
else
|
59
|
+
request = nil
|
60
|
+
response = SsrfFilter.get(@uri, headers: @remote_headers) do |req|
|
61
|
+
request = req
|
62
|
+
end
|
63
|
+
response.value
|
64
|
+
@file = StringIO.new(response.body)
|
65
|
+
@content_type = response.content_type
|
66
|
+
@headers = response
|
67
|
+
@uri = request.uri
|
68
|
+
end
|
45
69
|
end
|
46
70
|
@file
|
47
71
|
|
@@ -50,14 +74,14 @@ module CarrierWave
|
|
50
74
|
end
|
51
75
|
|
52
76
|
def filename_from_header
|
53
|
-
if
|
54
|
-
match =
|
77
|
+
if headers['content-disposition']
|
78
|
+
match = headers['content-disposition'].match(/filename="?([^"]+)/)
|
55
79
|
return match[1] unless match.nil? || match[1].empty?
|
56
80
|
end
|
57
81
|
end
|
58
82
|
|
59
83
|
def filename_from_uri
|
60
|
-
URI.
|
84
|
+
URI::DEFAULT_PARSER.unescape(File.basename(@uri.path))
|
61
85
|
end
|
62
86
|
|
63
87
|
def method_missing(*args, &block)
|
@@ -75,7 +99,7 @@ module CarrierWave
|
|
75
99
|
#
|
76
100
|
def download!(uri, remote_headers = {})
|
77
101
|
processed_uri = process_uri(uri)
|
78
|
-
file = RemoteFile.new(processed_uri, remote_headers)
|
102
|
+
file = RemoteFile.new(processed_uri, remote_headers, skip_ssrf_protection: skip_ssrf_protection?(processed_uri))
|
79
103
|
raise CarrierWave::DownloadError, "trying to download a file which is not served over HTTP" unless file.http?
|
80
104
|
cache!(file)
|
81
105
|
end
|
@@ -92,11 +116,30 @@ module CarrierWave
|
|
92
116
|
rescue URI::InvalidURIError
|
93
117
|
uri_parts = uri.split('?')
|
94
118
|
# regexp from Ruby's URI::Parser#regexp[:UNSAFE], with [] specifically removed
|
95
|
-
encoded_uri = URI.
|
96
|
-
encoded_uri << '?' << URI.
|
119
|
+
encoded_uri = URI::DEFAULT_PARSER.escape(uri_parts.shift, /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,]/)
|
120
|
+
encoded_uri << '?' << URI::DEFAULT_PARSER.escape(uri_parts.join('?')) if uri_parts.any?
|
97
121
|
URI.parse(encoded_uri) rescue raise CarrierWave::DownloadError, "couldn't parse URL"
|
98
122
|
end
|
99
123
|
|
124
|
+
##
|
125
|
+
# If this returns true, SSRF protection will be bypassed.
|
126
|
+
# You can override this if you want to allow accessing specific local URIs that are not SSRF exploitable.
|
127
|
+
#
|
128
|
+
# === Parameters
|
129
|
+
#
|
130
|
+
# [uri (URI)] The URI where the remote file is stored
|
131
|
+
#
|
132
|
+
# === Examples
|
133
|
+
#
|
134
|
+
# class MyUploader < CarrierWave::Uploader::Base
|
135
|
+
# def skip_ssrf_protection?(uri)
|
136
|
+
# uri.hostname == 'localhost' && uri.port == 80
|
137
|
+
# end
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
def skip_ssrf_protection?(uri)
|
141
|
+
false
|
142
|
+
end
|
100
143
|
end # Download
|
101
144
|
end # Uploader
|
102
145
|
end # CarrierWave
|
data/lib/carrierwave/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: carrierwave
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Nicklas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -53,33 +53,39 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.16'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: ssrf_filter
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "<"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
62
|
-
|
61
|
+
version: 1.1.0
|
62
|
+
- - "~>"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '1.0'
|
65
|
+
type: :runtime
|
63
66
|
prerelease: false
|
64
67
|
version_requirements: !ruby/object:Gem::Requirement
|
65
68
|
requirements:
|
66
|
-
- - "
|
69
|
+
- - "<"
|
67
70
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
71
|
+
version: 1.1.0
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.0'
|
69
75
|
- !ruby/object:Gem::Dependency
|
70
76
|
name: rails
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
72
78
|
requirements:
|
73
79
|
- - ">="
|
74
80
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
81
|
+
version: 5.0.0
|
76
82
|
type: :development
|
77
83
|
prerelease: false
|
78
84
|
version_requirements: !ruby/object:Gem::Requirement
|
79
85
|
requirements:
|
80
86
|
- - ">="
|
81
87
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
88
|
+
version: 5.0.0
|
83
89
|
- !ruby/object:Gem::Dependency
|
84
90
|
name: cucumber
|
85
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +128,20 @@ dependencies:
|
|
122
128
|
- - ">="
|
123
129
|
- !ruby/object:Gem::Version
|
124
130
|
version: '0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: fog-core
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: 2.1.0
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: 2.1.0
|
125
145
|
- !ruby/object:Gem::Dependency
|
126
146
|
name: fog-aws
|
127
147
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,16 +160,16 @@ dependencies:
|
|
140
160
|
name: fog-google
|
141
161
|
requirement: !ruby/object:Gem::Requirement
|
142
162
|
requirements:
|
143
|
-
- - "
|
163
|
+
- - ">="
|
144
164
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
165
|
+
version: '0'
|
146
166
|
type: :development
|
147
167
|
prerelease: false
|
148
168
|
version_requirements: !ruby/object:Gem::Requirement
|
149
169
|
requirements:
|
150
|
-
- - "
|
170
|
+
- - ">="
|
151
171
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
172
|
+
version: '0'
|
153
173
|
- !ruby/object:Gem::Dependency
|
154
174
|
name: fog-local
|
155
175
|
requirement: !ruby/object:Gem::Requirement
|
@@ -196,16 +216,16 @@ dependencies:
|
|
196
216
|
name: rmagick
|
197
217
|
requirement: !ruby/object:Gem::Requirement
|
198
218
|
requirements:
|
199
|
-
- - "
|
219
|
+
- - "~>"
|
200
220
|
- !ruby/object:Gem::Version
|
201
|
-
version: '
|
221
|
+
version: '2.16'
|
202
222
|
type: :development
|
203
223
|
prerelease: false
|
204
224
|
version_requirements: !ruby/object:Gem::Requirement
|
205
225
|
requirements:
|
206
|
-
- - "
|
226
|
+
- - "~>"
|
207
227
|
- !ruby/object:Gem::Version
|
208
|
-
version: '
|
228
|
+
version: '2.16'
|
209
229
|
- !ruby/object:Gem::Dependency
|
210
230
|
name: timecop
|
211
231
|
requirement: !ruby/object:Gem::Requirement
|
@@ -319,8 +339,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
319
339
|
- !ruby/object:Gem::Version
|
320
340
|
version: '0'
|
321
341
|
requirements: []
|
322
|
-
|
323
|
-
rubygems_version: 2.7.8
|
342
|
+
rubygems_version: 3.1.6
|
324
343
|
signing_key:
|
325
344
|
specification_version: 4
|
326
345
|
summary: Ruby file upload library
|