summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/gitlab/sanitizers/svg.rb23
-rw-r--r--spec/lib/gitlab/sanitizers/svg_spec.rb48
2 files changed, 66 insertions, 5 deletions
diff --git a/lib/gitlab/sanitizers/svg.rb b/lib/gitlab/sanitizers/svg.rb
index 5e95f6c0529..a540c534dee 100644
--- a/lib/gitlab/sanitizers/svg.rb
+++ b/lib/gitlab/sanitizers/svg.rb
@@ -13,12 +13,11 @@ module Gitlab
unless Whitelist::ALLOWED_ELEMENTS.include?(node.name)
node.unlink
else
- node.attributes.each do |attr_name, attr|
- valid_attributes = Whitelist::ALLOWED_ATTRIBUTES[node.name]
+ valid_attributes = Whitelist::ALLOWED_ATTRIBUTES[node.name]
- unless valid_attributes && valid_attributes.include?(attr_name)
- if Whitelist::ALLOWED_DATA_ATTRIBUTES_IN_ELEMENTS.include?(node.name) &&
- attr_name.start_with?('data-')
+ node.attribute_nodes.each do |attr|
+ unless valid_attributes && valid_attributes.include?(attribute_name_with_namespace(attr))
+ if Whitelist::ALLOWED_DATA_ATTRIBUTES_IN_ELEMENTS.include?(node.name) && data_attribute?(attr)
# Arbitrary data attributes are allowed. Verify that the attribute
# is a valid data attribute.
attr.unlink unless attr_name =~ DATA_ATTR_PATTERN
@@ -29,6 +28,20 @@ module Gitlab
end
end
end
+
+ def attribute_name_with_namespace(attr)
+ if attr.namespace
+ "#{attr.namespace.prefix}:#{attr.name}"
+ else
+ attr.name
+ end
+ end
+
+ private
+
+ def data_attribute?(attr)
+ attr.name.start_with?('data-')
+ end
end
end
end
diff --git a/spec/lib/gitlab/sanitizers/svg_spec.rb b/spec/lib/gitlab/sanitizers/svg_spec.rb
new file mode 100644
index 00000000000..bb1c98f51a6
--- /dev/null
+++ b/spec/lib/gitlab/sanitizers/svg_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+describe Gitlab::Sanitizers::SVG do
+ let(:scrubber) { Gitlab::Sanitizers::SVG::Scrubber.new }
+ let(:namespace) { double(Nokogiri::XML::Namespace, prefix: 'xlink') }
+ let(:namespaced_attr) { double(Nokogiri::XML::Attr, name: 'href', namespace: namespace) }
+
+ context 'scrubber' do
+ describe '#scrub' do
+ let(:invalid_element) { double(Nokogiri::XML::Node, name: 'invalid') }
+ let(:invalid_attribute) { double(Nokogiri::XML::Attr, name: 'invalid', namespace: nil) }
+ let(:valid_element) { double(Nokogiri::XML::Node, name: 'use') }
+
+ it 'removes an invalid element' do
+ expect(invalid_element).to receive(:unlink)
+
+ scrubber.scrub(invalid_element)
+ end
+
+ it 'removes an invalid attribute' do
+ allow(valid_element).to receive(:attribute_nodes) { [invalid_attribute] }
+ expect(invalid_attribute).to receive(:unlink)
+
+ scrubber.scrub(valid_element)
+ end
+
+ it 'accepts valid element' do
+ allow(valid_element).to receive(:attribute_nodes) { [namespaced_attr] }
+ expect(valid_element).not_to receive(:unlink)
+
+ scrubber.scrub(valid_element)
+ end
+
+ it 'accepts valid namespaced attributes' do
+ allow(valid_element).to receive(:attribute_nodes) { [namespaced_attr] }
+ expect(namespaced_attr).not_to receive(:unlink)
+
+ scrubber.scrub(valid_element)
+ end
+ end
+
+ describe '#attribute_name_with_namespace' do
+ it 'returns name with prefix when attribute is namespaced' do
+ expect(scrubber.attribute_name_with_namespace(namespaced_attr)).to eq('xlink:href')
+ end
+ end
+ end
+end