2018-11-19 21:01:13 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-03-25 01:39:58 -04:00
|
|
|
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
|
2019-05-05 06:19:14 -04:00
|
|
|
DATA_ATTR_PATTERN = /\Adata-(?!xml)[a-z_][\w.\u00E0-\u00F6\u00F8-\u017F\u01DD-\u02AF-]*\z/u.freeze
|
2016-03-25 01:39:58 -04:00
|
|
|
|
|
|
|
def scrub(node)
|
2016-06-03 15:08:43 -04:00
|
|
|
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
|
2016-03-25 01:39:58 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-06-01 23:37:25 -04:00
|
|
|
|
|
|
|
def attribute_name_with_namespace(attr)
|
|
|
|
if attr.namespace
|
|
|
|
"#{attr.namespace.prefix}:#{attr.name}"
|
|
|
|
else
|
|
|
|
attr.name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-03 15:08:43 -04:00
|
|
|
def allows_data_attribute?(node)
|
|
|
|
Whitelist::ALLOWED_DATA_ATTRIBUTES_IN_ELEMENTS.include?(node.name)
|
|
|
|
end
|
|
|
|
|
2016-06-01 23:52:35 -04:00
|
|
|
def unsafe_href?(attr)
|
2016-06-03 15:08:43 -04:00
|
|
|
attribute_name_with_namespace(attr) == 'xlink:href' && !attr.value.start_with?('#')
|
2016-06-01 23:52:35 -04:00
|
|
|
end
|
2016-06-01 23:37:25 -04:00
|
|
|
|
|
|
|
def data_attribute?(attr)
|
2016-06-03 15:08:43 -04:00
|
|
|
attr.name.start_with?('data-') && attr.name =~ DATA_ATTR_PATTERN && attr.namespace.nil?
|
2016-06-01 23:37:25 -04:00
|
|
|
end
|
2016-03-25 01:39:58 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|