carrierwave 1.3.1 → 1.3.2
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/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 +24 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5e6d1dd656203f5e14c43b75b807e793d623126006ddf8c5a4f9f4706faa750
|
4
|
+
data.tar.gz: 82281b939837f54716f580a1deb6397d87cc9bb867dc6a6938a4322d795500b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8eca3a53204f520d0cabf6e2384e6670cb634159e4b6c1e8d3915b6bab8473f21fb116047129b142a986588ea27401131d095186657770d7c31b03d6c929a1c9
|
7
|
+
data.tar.gz: 316797cffad6d2568e50929862cd80ba3e56c05d557f70f8631b66fc60ffd65fe5862afe4121a1e5e775e55a5f6c9a6c14414bce6a57deab2d12a8a127ed5b0d
|
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
|
|
@@ -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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Nicklas
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.16'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: ssrf_filter
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: pg
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -196,16 +210,16 @@ dependencies:
|
|
196
210
|
name: rmagick
|
197
211
|
requirement: !ruby/object:Gem::Requirement
|
198
212
|
requirements:
|
199
|
-
- - "
|
213
|
+
- - "~>"
|
200
214
|
- !ruby/object:Gem::Version
|
201
|
-
version: '
|
215
|
+
version: '2.16'
|
202
216
|
type: :development
|
203
217
|
prerelease: false
|
204
218
|
version_requirements: !ruby/object:Gem::Requirement
|
205
219
|
requirements:
|
206
|
-
- - "
|
220
|
+
- - "~>"
|
207
221
|
- !ruby/object:Gem::Version
|
208
|
-
version: '
|
222
|
+
version: '2.16'
|
209
223
|
- !ruby/object:Gem::Dependency
|
210
224
|
name: timecop
|
211
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -303,7 +317,7 @@ homepage: https://github.com/carrierwaveuploader/carrierwave
|
|
303
317
|
licenses:
|
304
318
|
- MIT
|
305
319
|
metadata: {}
|
306
|
-
post_install_message:
|
320
|
+
post_install_message:
|
307
321
|
rdoc_options:
|
308
322
|
- "--main"
|
309
323
|
require_paths:
|
@@ -319,9 +333,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
319
333
|
- !ruby/object:Gem::Version
|
320
334
|
version: '0'
|
321
335
|
requirements: []
|
322
|
-
|
323
|
-
|
324
|
-
signing_key:
|
336
|
+
rubygems_version: 3.1.2
|
337
|
+
signing_key:
|
325
338
|
specification_version: 4
|
326
339
|
summary: Ruby file upload library
|
327
340
|
test_files: []
|