From 02b882418a44bccbcde403886c560505abd60281 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Thu, 2 Jun 2016 00:37:25 -0300 Subject: Fix SVG whitelisting to allow namespaced attributes --- lib/gitlab/sanitizers/svg.rb | 23 ++++++++++++---- spec/lib/gitlab/sanitizers/svg_spec.rb | 48 ++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 spec/lib/gitlab/sanitizers/svg_spec.rb 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 -- cgit v1.2.1