Commit b0c1ebfd authored by Changzheng Liu's avatar Changzheng Liu Committed by Patrick Bajao

Sanitize issue description in search result

parent 6f95667d
...@@ -360,33 +360,31 @@ module SearchHelper ...@@ -360,33 +360,31 @@ module SearchHelper
end end
end end
def search_md_sanitize(source)
search_sanitize(markdown(search_truncate(source)))
end
def simple_search_highlight_and_truncate(text, phrase, options = {})
highlight(search_sanitize(search_truncate(text)), phrase.split, options)
end
# Sanitize a HTML field for search display. Most tags are stripped out and the # Sanitize a HTML field for search display. Most tags are stripped out and the
# maximum length is set to 200 characters. # maximum length is set to 200 characters.
def search_md_sanitize(source) def search_truncate(source)
source = Truncato.truncate( Truncato.truncate(
source, source,
count_tags: false, count_tags: false,
count_tail: false, count_tail: false,
filtered_tags: %w(img),
max_length: 200 max_length: 200
) )
end
html = markdown(source) def search_sanitize(html)
# Truncato's filtered_tags and filtered_attributes are not quite the same # Truncato's filtered_tags and filtered_attributes are not quite the same
sanitize(html, tags: %w(a p ol ul li pre code)) sanitize(html, tags: %w(a p ol ul li pre code))
end end
def simple_search_highlight_and_truncate(text, phrase, options = {})
text = Truncato.truncate(
text,
count_tags: false,
count_tail: false,
max_length: options.delete(:length) { 200 }
)
highlight(text, phrase.split, options)
end
# _search_highlight is used in EE override # _search_highlight is used in EE override
def highlight_and_truncate_issuable(issuable, search_term, _search_highlight) def highlight_and_truncate_issuable(issuable, search_term, _search_highlight)
return unless issuable.description.present? return unless issuable.description.present?
......
---
title: Sanitize issue description in search result
merge_request: 56256
author:
type: fixed
...@@ -79,7 +79,7 @@ module EE ...@@ -79,7 +79,7 @@ module EE
text = sanitize(search_highlight[issuable.id].description.first) text = sanitize(search_highlight[issuable.id].description.first)
text.gsub!(::Elastic::Latest::GitClassProxy::HIGHLIGHT_START_TAG, '<span class="gl-text-gray-900 gl-font-weight-bold">') text.gsub!(::Elastic::Latest::GitClassProxy::HIGHLIGHT_START_TAG, '<span class="gl-text-gray-900 gl-font-weight-bold">')
text.gsub!(::Elastic::Latest::GitClassProxy::HIGHLIGHT_END_TAG, '</span>') text.gsub!(::Elastic::Latest::GitClassProxy::HIGHLIGHT_END_TAG, '</span>')
Truncato.truncate(text, count_tags: false, count_tail: false, max_length: 200).html_safe search_truncate(text).html_safe
end end
def advanced_search_status_marker(project) def advanced_search_status_marker(project)
......
...@@ -170,7 +170,7 @@ RSpec.describe 'Global elastic search', :elastic, :sidekiq_inline do ...@@ -170,7 +170,7 @@ RSpec.describe 'Global elastic search', :elastic, :sidekiq_inline do
submit_search('term') submit_search('term')
select_search_scope('Wiki') select_search_scope('Wiki')
expect(page).to have_selector('.search-result-row .description', text: '# term') expect(page).to have_selector('.search-result-row .description', text: 'term')
expect(page).to have_link('test') expect(page).to have_link('test')
end end
end end
......
...@@ -75,7 +75,7 @@ RSpec.describe 'Group elastic search', :js, :elastic, :sidekiq_might_not_need_in ...@@ -75,7 +75,7 @@ RSpec.describe 'Group elastic search', :js, :elastic, :sidekiq_might_not_need_in
submit_search('term') submit_search('term')
select_search_scope('Wiki') select_search_scope('Wiki')
expect(page).to have_selector('.search-result-row .description', text: '# term') expect(page).to have_selector('.search-result-row .description', text: 'term')
expect(page).to have_link('test') expect(page).to have_link('test')
end end
end end
......
...@@ -232,6 +232,7 @@ RSpec.describe SearchHelper do ...@@ -232,6 +232,7 @@ RSpec.describe SearchHelper do
'<a href="#" onclick="alert(\'XSS\')">Click Me test</a>' | { 1 => { description: ['<a href="#" onclick="alert(\'XSS\')">Click Me gitlabelasticsearch→test←gitlabelasticsearch</a>'] } } | "<a href='#'>Click Me <span class='gl-text-gray-900 gl-font-weight-bold'>test</span></a>" '<a href="#" onclick="alert(\'XSS\')">Click Me test</a>' | { 1 => { description: ['<a href="#" onclick="alert(\'XSS\')">Click Me gitlabelasticsearch→test←gitlabelasticsearch</a>'] } } | "<a href='#'>Click Me <span class='gl-text-gray-900 gl-font-weight-bold'>test</span></a>"
'<script type="text/javascript">alert(\'Another XSS\');</script> test' | { 1 => { description: ['<script type="text/javascript">alert(\'Another XSS\');</script> gitlabelasticsearch→test←gitlabelasticsearch'] } } | "alert(&apos;Another XSS&apos;); <span class='gl-text-gray-900 gl-font-weight-bold'>test</span>" '<script type="text/javascript">alert(\'Another XSS\');</script> test' | { 1 => { description: ['<script type="text/javascript">alert(\'Another XSS\');</script> gitlabelasticsearch→test←gitlabelasticsearch'] } } | "alert(&apos;Another XSS&apos;); <span class='gl-text-gray-900 gl-font-weight-bold'>test</span>"
'Lorem test ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec.' | { 1 => { description: ['Lorem gitlabelasticsearch→test←gitlabelasticsearch ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec.'] } } | "Lorem <span class='gl-text-gray-900 gl-font-weight-bold'>test</span> ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Don..." 'Lorem test ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec.' | { 1 => { description: ['Lorem gitlabelasticsearch→test←gitlabelasticsearch ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec.'] } } | "Lorem <span class='gl-text-gray-900 gl-font-weight-bold'>test</span> ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Don..."
'<img src="https://random.foo.com/test.png" width="128" height="128" />some image' | { 1 => { description: ['<img src="https://random.foo.com/gitlabelasticsearch→test←gitlabelasticsearch.png" width="128" height="128" />some image'] } } | 'some image'
end end
with_them do with_them do
......
...@@ -534,10 +534,11 @@ RSpec.describe SearchHelper do ...@@ -534,10 +534,11 @@ RSpec.describe SearchHelper do
where(:description, :expected) do where(:description, :expected) do
'test' | '<span class="gl-text-gray-900 gl-font-weight-bold">test</span>' 'test' | '<span class="gl-text-gray-900 gl-font-weight-bold">test</span>'
'<span style="color: blue;">this test should not be blue</span>' | '<span>this <span class="gl-text-gray-900 gl-font-weight-bold">test</span> should not be blue</span>' '<span style="color: blue;">this test should not be blue</span>' | 'this <span class="gl-text-gray-900 gl-font-weight-bold">test</span> should not be blue'
'<a href="#" onclick="alert(\'XSS\')">Click Me test</a>' | '<a href="#">Click Me <span class="gl-text-gray-900 gl-font-weight-bold">test</span></a>' '<a href="#" onclick="alert(\'XSS\')">Click Me test</a>' | '<a href="#">Click Me <span class="gl-text-gray-900 gl-font-weight-bold">test</span></a>'
'<script type="text/javascript">alert(\'Another XSS\');</script> test' | ' <span class="gl-text-gray-900 gl-font-weight-bold">test</span>' '<script type="text/javascript">alert(\'Another XSS\');</script> test' | ' <span class="gl-text-gray-900 gl-font-weight-bold">test</span>'
'Lorem test ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec.' | 'Lorem <span class="gl-text-gray-900 gl-font-weight-bold">test</span> ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Don...' 'Lorem test ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec.' | 'Lorem <span class="gl-text-gray-900 gl-font-weight-bold">test</span> ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Don...'
'<img src="https://random.foo.com/test.png" width="128" height="128" />some image' | 'some image'
end end
with_them do with_them do
......
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