summaryrefslogtreecommitdiff
path: root/lib/gitlab/sanitizers/svg.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/sanitizers/svg.rb')
-rw-r--r--lib/gitlab/sanitizers/svg.rb57
1 files changed, 57 insertions, 0 deletions
diff --git a/lib/gitlab/sanitizers/svg.rb b/lib/gitlab/sanitizers/svg.rb
new file mode 100644
index 00000000000..8304b9a482c
--- /dev/null
+++ b/lib/gitlab/sanitizers/svg.rb
@@ -0,0 +1,57 @@
+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)
+ 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
+ end
+ end
+ end
+ end
+
+ def attribute_name_with_namespace(attr)
+ if attr.namespace
+ "#{attr.namespace.prefix}:#{attr.name}"
+ else
+ attr.name
+ end
+ end
+
+ def allows_data_attribute?(node)
+ Whitelist::ALLOWED_DATA_ATTRIBUTES_IN_ELEMENTS.include?(node.name)
+ end
+
+ def unsafe_href?(attr)
+ attribute_name_with_namespace(attr) == 'xlink:href' && !attr.value.start_with?('#')
+ end
+
+ def data_attribute?(attr)
+ attr.name.start_with?('data-') && attr.name =~ DATA_ATTR_PATTERN && attr.namespace.nil?
+ end
+ end
+ end
+ end
+end