Commit b905702d authored by Robert Speicher's avatar Robert Speicher

Escape title attributes in references

parent a3c71d98
...@@ -109,5 +109,6 @@ module IssuesHelper ...@@ -109,5 +109,6 @@ module IssuesHelper
end end
end end
# Required for Gitlab::Markdown::IssueReferenceFilter
module_function :url_for_issue, :title_for_issue module_function :url_for_issue, :title_for_issue
end end
module LabelsHelper module LabelsHelper
include ActionView::Helpers::TagHelper
def project_label_names def project_label_names
@project.labels.pluck(:title) @project.labels.pluck(:title)
end end
...@@ -11,7 +13,7 @@ module LabelsHelper ...@@ -11,7 +13,7 @@ module LabelsHelper
# by LabelReferenceFilter # by LabelReferenceFilter
span = %(<span class="label color-label") + span = %(<span class="label color-label") +
%( style="background-color: #{label_color}; color: #{text_color}">) + %( style="background-color: #{label_color}; color: #{text_color}">) +
label.name + '</span>' escape_once(label.name) + '</span>'
span.html_safe span.html_safe
end end
...@@ -56,5 +58,6 @@ module LabelsHelper ...@@ -56,5 +58,6 @@ module LabelsHelper
options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name]) options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name])
end end
module_function :render_colored_label, :text_color_for_bg # Required for Gitlab::Markdown::LabelReferenceFilter
module_function :render_colored_label, :text_color_for_bg, :escape_once
end end
...@@ -50,7 +50,7 @@ module Gitlab ...@@ -50,7 +50,7 @@ module Gitlab
if project.valid_repo? && commit = project.repository.commit(commit_ref) if project.valid_repo? && commit = project.repository.commit(commit_ref)
url = url_for_commit(project, commit) url = url_for_commit(project, commit)
title = commit.link_title title = escape_once(commit.link_title)
klass = reference_class(:commit) klass = reference_class(:commit)
project_ref += '@' if project_ref project_ref += '@' if project_ref
......
...@@ -46,7 +46,7 @@ module Gitlab ...@@ -46,7 +46,7 @@ module Gitlab
self.class.references_in(text) do |match, issue| self.class.references_in(text) do |match, issue|
url = url_for_issue(issue, project, only_path: context[:only_path]) url = url_for_issue(issue, project, only_path: context[:only_path])
title = "Issue in #{project.external_issue_tracker.title}" title = escape_once("Issue in #{project.external_issue_tracker.title}")
klass = reference_class(:issue) klass = reference_class(:issue)
%(<a href="#{url}" %(<a href="#{url}"
......
...@@ -50,7 +50,7 @@ module Gitlab ...@@ -50,7 +50,7 @@ module Gitlab
if project.issue_exists?(issue) if project.issue_exists?(issue)
url = url_for_issue(issue, project, only_path: context[:only_path]) url = url_for_issue(issue, project, only_path: context[:only_path])
title = "Issue: #{title_for_issue(issue, project)}" title = escape_once("Issue: #{title_for_issue(issue, project)}")
klass = reference_class(:issue) klass = reference_class(:issue)
%(<a href="#{url}" %(<a href="#{url}"
......
...@@ -52,7 +52,7 @@ module Gitlab ...@@ -52,7 +52,7 @@ module Gitlab
project = self.project_from_ref(project_ref) project = self.project_from_ref(project_ref)
if merge_request = project.merge_requests.find_by(iid: id) if merge_request = project.merge_requests.find_by(iid: id)
title = "Merge Request: #{merge_request.title}" title = escape_once("Merge Request: #{merge_request.title}")
klass = reference_class(:merge_request) klass = reference_class(:merge_request)
url = url_for_merge_request(merge_request, project) url = url_for_merge_request(merge_request, project)
......
require 'active_support/core_ext/string/output_safety'
require 'html/pipeline' require 'html/pipeline'
module Gitlab module Gitlab
...@@ -12,6 +13,10 @@ module Gitlab ...@@ -12,6 +13,10 @@ module Gitlab
# :only_path - Generate path-only links. # :only_path - Generate path-only links.
# #
class ReferenceFilter < HTML::Pipeline::Filter class ReferenceFilter < HTML::Pipeline::Filter
def escape_once(html)
ERB::Util.html_escape_once(html)
end
# Don't look for references in text nodes that are children of these # Don't look for references in text nodes that are children of these
# elements. # elements.
IGNORE_PARENTS = %w(pre code a style).to_set IGNORE_PARENTS = %w(pre code a style).to_set
......
...@@ -48,7 +48,7 @@ module Gitlab ...@@ -48,7 +48,7 @@ module Gitlab
project = self.project_from_ref(project_ref) project = self.project_from_ref(project_ref)
if snippet = project.snippets.find_by(id: id) if snippet = project.snippets.find_by(id: id)
title = "Snippet: #{snippet.title}" title = escape_once("Snippet: #{snippet.title}")
klass = reference_class(:snippet) klass = reference_class(:snippet)
url = url_for_snippet(snippet, project) url = url_for_snippet(snippet, project)
......
...@@ -51,6 +51,13 @@ module Gitlab::Markdown ...@@ -51,6 +51,13 @@ module Gitlab::Markdown
expect(doc.css('a').first.attr('title')).to eq commit.link_title expect(doc.css('a').first.attr('title')).to eq commit.link_title
end end
it 'escapes the title attribute' do
allow_any_instance_of(Commit).to receive(:title).and_return(%{"></a>whatever<a title="})
doc = filter("See #{reference}")
expect(doc.text).to eq "See #{commit.id}"
end
it 'includes default classes' do it 'includes default classes' do
doc = filter("See #{reference}") doc = filter("See #{reference}")
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit' expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit'
......
...@@ -80,6 +80,14 @@ module Gitlab::Markdown ...@@ -80,6 +80,14 @@ module Gitlab::Markdown
expect(doc.css('a').first.attr('title')).to eq "Issue in JIRA tracker" expect(doc.css('a').first.attr('title')).to eq "Issue in JIRA tracker"
end end
it 'escapes the title attribute' do
allow(project.external_issue_tracker).to receive(:title).
and_return(%{"></a>whatever<a title="})
doc = filter("Issue #{reference}")
expect(doc.text).to eq "Issue #{reference}"
end
it 'includes default classes' do it 'includes default classes' do
doc = filter("Issue #{reference}") doc = filter("Issue #{reference}")
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue' expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue'
......
...@@ -57,6 +57,13 @@ module Gitlab::Markdown ...@@ -57,6 +57,13 @@ module Gitlab::Markdown
expect(doc.css('a').first.attr('title')).to eq "Issue: #{issue.title}" expect(doc.css('a').first.attr('title')).to eq "Issue: #{issue.title}"
end end
it 'escapes the title attribute' do
issue.update_attribute(:title, %{"></a>whatever<a title="})
doc = filter("Issue #{reference}")
expect(doc.text).to eq "Issue #{reference}"
end
it 'includes default classes' do it 'includes default classes' do
doc = filter("Issue #{reference}") doc = filter("Issue #{reference}")
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue' expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue'
......
...@@ -45,6 +45,13 @@ module Gitlab::Markdown ...@@ -45,6 +45,13 @@ module Gitlab::Markdown
expect(doc.css('a').first.attr('title')).to eq "Merge Request: #{merge.title}" expect(doc.css('a').first.attr('title')).to eq "Merge Request: #{merge.title}"
end end
it 'escapes the title attribute' do
merge.update_attribute(:title, %{"></a>whatever<a title="})
doc = filter("Merge #{reference}")
expect(doc.text).to eq "Merge #{reference}"
end
it 'includes default classes' do it 'includes default classes' do
doc = filter("Merge #{reference}") doc = filter("Merge #{reference}")
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-merge_request' expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-merge_request'
......
...@@ -44,6 +44,13 @@ module Gitlab::Markdown ...@@ -44,6 +44,13 @@ module Gitlab::Markdown
expect(doc.css('a').first.attr('title')).to eq "Snippet: #{snippet.title}" expect(doc.css('a').first.attr('title')).to eq "Snippet: #{snippet.title}"
end end
it 'escapes the title attribute' do
snippet.update_attribute(:title, %{"></a>whatever<a title="})
doc = filter("Snippet #{reference}")
expect(doc.text).to eq "Snippet #{reference}"
end
it 'includes default classes' do it 'includes default classes' do
doc = filter("Snippet #{reference}") doc = filter("Snippet #{reference}")
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-snippet' expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-snippet'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment