BigW Consortium Gitlab

svg.rb 1.73 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
module Gitlab
  module Sanitizers
    module SVG
      def self.clean(data)
        Loofah.xml_document(data).scrub!(Scrubber.new).to_s
      end

      class Scrubber < Loofah::Scrubber
        # http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data-with-the-data-*-attributes
        DATA_ATTR_PATTERN = /\Adata-(?!xml)[a-z_][\w.\u00E0-\u00F6\u00F8-\u017F\u01DD-\u02AF-]*\z/u

        def scrub(node)
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
          unless Whitelist::ALLOWED_ELEMENTS.include?(node.name)
            node.unlink
            return
          end

          valid_attributes = Whitelist::ALLOWED_ATTRIBUTES[node.name]
          return unless valid_attributes

          node.attribute_nodes.each do |attr|
            attr_name = attribute_name_with_namespace(attr)

            if valid_attributes.include?(attr_name)
              attr.unlink if unsafe_href?(attr)
            else
              # Arbitrary data attributes are allowed.
              unless allows_data_attribute?(node) && data_attribute?(attr)
                attr.unlink
30 31 32 33
              end
            end
          end
        end
34 35 36 37 38 39 40 41 42

        def attribute_name_with_namespace(attr)
          if attr.namespace
            "#{attr.namespace.prefix}:#{attr.name}"
          else
            attr.name
          end
        end

43 44 45 46
        def allows_data_attribute?(node)
          Whitelist::ALLOWED_DATA_ATTRIBUTES_IN_ELEMENTS.include?(node.name)
        end

47
        def unsafe_href?(attr)
48
          attribute_name_with_namespace(attr) == 'xlink:href' && !attr.value.start_with?('#')
49
        end
50 51

        def data_attribute?(attr)
52
          attr.name.start_with?('data-') && attr.name =~ DATA_ATTR_PATTERN && attr.namespace.nil?
53
        end
54 55 56 57
      end
    end
  end
end