Rafał Jaroszewicz

Using inline SVGs with Rails attachments

So I was looking for a method to serve attachments uploaded by users in the Rails Active Storage. Regardless of where these are served from, I needed a way to insert them into the document.

I read This article by Salazar explaining how to serve SVG icon packs and I realized that with a small tweak, I can use it for my case.

  def show_svg(attachment, options = {})
    return if !attachment.content_type.include?('svg')

    attachment.open do |file|
      content = file.read
      doc = Nokogiri::HTML::DocumentFragment.parse content
      svg = doc.at_css 'svg'

      # for security
      doc.search('script').each do |src|
        src.remove
      end

      options.each { |attr, value| svg[attr.to_s] = value }

      doc.to_html.html_safe
    end
  end

I added a few security measure to ensure that we are only displaying SVG, I’m making sure that only this type of file is served and also just in case, stripping <script> tags.

Try it:

<svg>
  <script>alert(1)</script>
</svg>

Once that method is set up, I can just pass in the attachment in the view. get_image_url is just a custom method to retrieve a link to this image.

<% if post.image.content_type.include? 'svg' %>
  <%= show_svg post.image %>
<% else %>
  <%= image_tag post.get_image_url(variant: :small) %>
<% end %>

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top