Search code examples
ruby-on-railsrubysvgcarrierwave

Rails, how to make carrierwave upload SVGs again?


I am upgrading a Rails app fro 3 to 7. With the new App Carrierwave stopped to accept SVG files for upload. Previously I could upload svg files, without processing and the creation of versions with this setting:

class LogoUploader < CarrierWave::Uploader::Base

  include CarrierWave::MiniMagick
  include CarrierWave::MimeTypes

  process :set_content_type

  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{model.id}"
  end

end

Since version 0.11.0 of Carriwave set_content_type appears to have been deprecated. Which leaves my SVG Uploader with just:

class LogoUploader < CarrierWave::Uploader::Base

  include CarrierWave::MiniMagick

  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{model.id}"
  end

  def content_type_allowlist
    [/image\//]
  end

end

I do not want to convert the svg and the upload is protected and only available to admins. Currently I do not get beyond the submit button.

When trying to upload I now get the following response:

Started PATCH "/admin/logos/18" for ::1 at 2022-06-18 10:01:19 +0200
Processing by Admin::LogosController#update as TURBO_STREAM
  Parameters: {"authenticity_token"=>"[FILTERED]", "logo"=>{"file_name"=>#<ActionDispatch::Http::UploadedFile:0x00007ff1803932c0 @tempfile=#<Tempfile:/var/folders/yg/pfjwzpkx5wq9d27svk760h0h0000gn/T/RackMultipart20220618-29575-j47l79.svg>, @original_filename="some-name.svg", @content_type="image/svg+xml", @headers="Content-Disposition: form-data; name=\"logo[file_name]\"; filename=\"some-name.svg\"\r\nContent-Type: image/svg+xml\r\n">}, "commit"=>"Save", "id"=>"18"}
  ...
Completed 200 OK in 92ms (Views: 10.5ms | ActiveRecord: 0.5ms | Allocations: 8188)

I tried to add [/image\/svg+xml//] to the content_type_allowlist and got beyond the submit button, but received the error "Nil location provided. Can't build URI."

Parameters:

{"_method"=>"patch",
 "authenticity_token"=>"[FILTERED]",
 "logo"=>
  {"file_name"=>
    #<ActionDispatch::Http::UploadedFile:0x00007fb111dae5c0
     @content_type="image/svg+xml",
     @headers="Content-Disposition: form-data; name=\"logo[file_name]\"; filename=\"some-name.svg\"\r\n" + "Content-Type: image/svg+xml\r\n",
     @original_filename="some-name.svg",
     @tempfile=#<File:/var/folders/yg/pfjwzpkx5wq9d27svk760h0h0000gn/T/RackMultipart20220618-86477-ij7mr4.svg>>},
 "commit"=>"Save",
 "id"=>"18"}

I guess I have encountered the Carrierwave CVE-2016-3714 mitigation. In RubyDocs they say to either disable ImageMagick's default SVG delegate or use RSVG delegate for SVG processing.

How can I disable ImageMagick's default SVG delegate? How do I use RSVG delegate?

Thank you in advance.


Solution

  • I discovered that in my case it was not related to ImageMagick, but to the validation of belongs_to associations introduced with Rails 5.

    I had to put optional: true in the logo model and now it is uploading again. This means, that in my setting (no conversion of svg files) you can still upload svgs.

    class Logo < ApplicationRecord
    
      mount_uploader :file_name, LogoUploader
    
      belongs_to :institution, optional: true
    
    ...
    
    end
    

    I am still curious how someone would have to configure ImageMagick both on Ubuntu and MacOS. If you know, please share ...