Add a `pipeline` context option for SanitizationFilter
When this option is `:description`, we use a more restrictive whitelist. This is used for Project and Group description fields.
This commit is contained in:
parent
1a52f19c45
commit
023dd2907b
|
@ -11,7 +11,7 @@
|
||||||
@#{@group.path}
|
@#{@group.path}
|
||||||
- if @group.description.present?
|
- if @group.description.present?
|
||||||
.description
|
.description
|
||||||
= markdown(@group.description)
|
= markdown(@group.description, pipeline: :description)
|
||||||
%hr
|
%hr
|
||||||
|
|
||||||
= render 'shared/show_aside'
|
= render 'shared/show_aside'
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
.project-home-row.project-home-row-top
|
.project-home-row.project-home-row-top
|
||||||
.project-home-desc
|
.project-home-desc
|
||||||
- if @project.description.present?
|
- if @project.description.present?
|
||||||
= markdown(@project.description)
|
= markdown(@project.description, pipeline: :description)
|
||||||
- if can?(current_user, :admin_project, @project)
|
- if can?(current_user, :admin_project, @project)
|
||||||
–
|
–
|
||||||
= link_to 'Edit', edit_namespace_project_path
|
= link_to 'Edit', edit_namespace_project_path
|
||||||
|
|
|
@ -57,6 +57,9 @@ module Gitlab
|
||||||
pipeline = HTML::Pipeline.new(filters)
|
pipeline = HTML::Pipeline.new(filters)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
|
# SanitizationFilter
|
||||||
|
pipeline: options[:pipeline],
|
||||||
|
|
||||||
# EmojiFilter
|
# EmojiFilter
|
||||||
asset_root: Gitlab.config.gitlab.url,
|
asset_root: Gitlab.config.gitlab.url,
|
||||||
asset_host: Gitlab::Application.config.asset_host,
|
asset_host: Gitlab::Application.config.asset_host,
|
||||||
|
|
|
@ -8,33 +8,53 @@ module Gitlab
|
||||||
# Extends HTML::Pipeline::SanitizationFilter with a custom whitelist.
|
# Extends HTML::Pipeline::SanitizationFilter with a custom whitelist.
|
||||||
class SanitizationFilter < HTML::Pipeline::SanitizationFilter
|
class SanitizationFilter < HTML::Pipeline::SanitizationFilter
|
||||||
def whitelist
|
def whitelist
|
||||||
whitelist = super
|
# Descriptions are more heavily sanitized, allowing only a few elements.
|
||||||
|
# See http://git.io/vkuAN
|
||||||
# Only push these customizations once
|
if pipeline == :description
|
||||||
unless customized?(whitelist[:transformers])
|
whitelist = LIMITED
|
||||||
# Allow code highlighting
|
else
|
||||||
whitelist[:attributes]['pre'] = %w(class)
|
whitelist = super
|
||||||
whitelist[:attributes]['span'] = %w(class)
|
|
||||||
|
|
||||||
# Allow table alignment
|
|
||||||
whitelist[:attributes]['th'] = %w(style)
|
|
||||||
whitelist[:attributes]['td'] = %w(style)
|
|
||||||
|
|
||||||
# Allow span elements
|
|
||||||
whitelist[:elements].push('span')
|
|
||||||
|
|
||||||
# Remove `rel` attribute from `a` elements
|
|
||||||
whitelist[:transformers].push(remove_rel)
|
|
||||||
|
|
||||||
# Remove `class` attribute from non-highlight spans
|
|
||||||
whitelist[:transformers].push(clean_spans)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
customize_whitelist(whitelist)
|
||||||
|
|
||||||
whitelist
|
whitelist
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def pipeline
|
||||||
|
context[:pipeline] || :default
|
||||||
|
end
|
||||||
|
|
||||||
|
def customized?(transformers)
|
||||||
|
transformers.last.source_location[0] == __FILE__
|
||||||
|
end
|
||||||
|
|
||||||
|
def customize_whitelist(whitelist)
|
||||||
|
# Only push these customizations once
|
||||||
|
return if customized?(whitelist[:transformers])
|
||||||
|
|
||||||
|
# Allow code highlighting
|
||||||
|
whitelist[:attributes]['pre'] = %w(class)
|
||||||
|
whitelist[:attributes]['span'] = %w(class)
|
||||||
|
|
||||||
|
# Allow table alignment
|
||||||
|
whitelist[:attributes]['th'] = %w(style)
|
||||||
|
whitelist[:attributes]['td'] = %w(style)
|
||||||
|
|
||||||
|
# Allow span elements
|
||||||
|
whitelist[:elements].push('span')
|
||||||
|
|
||||||
|
# Remove `rel` attribute from `a` elements
|
||||||
|
whitelist[:transformers].push(remove_rel)
|
||||||
|
|
||||||
|
# Remove `class` attribute from non-highlight spans
|
||||||
|
whitelist[:transformers].push(clean_spans)
|
||||||
|
|
||||||
|
whitelist
|
||||||
|
end
|
||||||
|
|
||||||
def remove_rel
|
def remove_rel
|
||||||
lambda do |env|
|
lambda do |env|
|
||||||
if env[:node_name] == 'a'
|
if env[:node_name] == 'a'
|
||||||
|
@ -53,10 +73,6 @@ module Gitlab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def customized?(transformers)
|
|
||||||
transformers.last.source_location[0] == __FILE__
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,6 +42,13 @@ module Gitlab::Markdown
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'custom whitelist' do
|
describe 'custom whitelist' do
|
||||||
|
it 'customizes the whitelist only once' do
|
||||||
|
instance = described_class.new('Foo')
|
||||||
|
3.times { instance.whitelist }
|
||||||
|
|
||||||
|
expect(instance.whitelist[:transformers].size).to eq 4
|
||||||
|
end
|
||||||
|
|
||||||
it 'allows syntax highlighting' do
|
it 'allows syntax highlighting' do
|
||||||
exp = act = %q{<pre class="code highlight white c"><code><span class="k">def</span></code></pre>}
|
exp = act = %q{<pre class="code highlight white c"><code><span class="k">def</span></code></pre>}
|
||||||
expect(filter(act).to_html).to eq exp
|
expect(filter(act).to_html).to eq exp
|
||||||
|
@ -87,5 +94,12 @@ module Gitlab::Markdown
|
||||||
expect(doc.at_css('a')['href']).to be_nil
|
expect(doc.at_css('a')['href']).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when pipeline is :description' do
|
||||||
|
it 'uses a stricter whitelist' do
|
||||||
|
doc = filter('<h1>My Project</h1>', pipeline: :description)
|
||||||
|
expect(doc.to_html.strip).to eq 'My Project'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue