mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 09:26:54 -06:00
FIX: Apply censored words to inline onebox (#16873)
Censored watched words were not censored inside the title of an inline
oneboxes. Malicious users could exploit this behaviour to insert bad
words. The same issue has been fixed for regular Oneboxes in commit
d184fe59ca
.
This commit is contained in:
parent
6268fe7495
commit
7328a2bfb0
@ -103,21 +103,18 @@ class WordWatcher
|
||||
|
||||
doc = Nokogiri::HTML5::fragment(html)
|
||||
doc.traverse do |node|
|
||||
if node.text?
|
||||
node.content = node.content.gsub(regexp) do |match|
|
||||
# the regex captures leading whitespaces
|
||||
padding = match.size - match.lstrip.size
|
||||
if padding > 0
|
||||
match[0..padding - 1] + REPLACEMENT_LETTER * (match.size - padding)
|
||||
else
|
||||
REPLACEMENT_LETTER * match.size
|
||||
end
|
||||
end
|
||||
end
|
||||
node.content = censor_text_with_regexp(node.content, regexp) if node.text?
|
||||
end
|
||||
doc.to_s
|
||||
end
|
||||
|
||||
def self.censor_text(text)
|
||||
regexp = WordWatcher.word_matcher_regexp(:censor)
|
||||
return text if regexp.blank?
|
||||
|
||||
censor_text_with_regexp(text, regexp)
|
||||
end
|
||||
|
||||
def self.clear_cache!
|
||||
WatchedWord.actions.each do |a, i|
|
||||
Discourse.cache.delete word_matcher_regexp_key(a)
|
||||
@ -172,4 +169,18 @@ class WordWatcher
|
||||
def word_matches?(word)
|
||||
Regexp.new(WordWatcher.word_to_regexp(word, whole: true), Regexp::IGNORECASE).match?(@raw)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.censor_text_with_regexp(text, regexp)
|
||||
text.gsub(regexp) do |match|
|
||||
# the regex captures leading whitespaces
|
||||
padding = match.size - match.lstrip.size
|
||||
if padding > 0
|
||||
match[0..padding - 1] + REPLACEMENT_LETTER * (match.size - padding)
|
||||
else
|
||||
REPLACEMENT_LETTER * match.size
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -108,6 +108,7 @@ class InlineOneboxer
|
||||
end
|
||||
end
|
||||
onebox = { url: url, title: title && Emoji.gsub_emoji_to_unicode(title) }
|
||||
onebox[:title] = WordWatcher.censor_text(onebox[:title])
|
||||
Discourse.cache.write(cache_key(url), onebox, expires_in: 1.day) if !opts[:skip_cache]
|
||||
onebox
|
||||
end
|
||||
|
@ -313,6 +313,24 @@ describe InlineOneboxer do
|
||||
expect(onebox[:title]).to be_blank
|
||||
end
|
||||
end
|
||||
|
||||
it "censors external oneboxes" do
|
||||
Fabricate(:watched_word, action: WatchedWord.actions[:censor], word: "my")
|
||||
|
||||
SiteSetting.enable_inline_onebox_on_all_domains = true
|
||||
|
||||
stub_request(:get, "https://eviltrout.com/some-path").
|
||||
to_return(status: 200, body: "<html><head><title>welcome to my blog</title></head></html>")
|
||||
|
||||
onebox = InlineOneboxer.lookup(
|
||||
"https://eviltrout.com/some-path",
|
||||
skip_cache: true
|
||||
)
|
||||
|
||||
expect(onebox).to be_present
|
||||
expect(onebox[:url]).to eq("https://eviltrout.com/some-path")
|
||||
expect(onebox[:title]).to eq("welcome to ■■ blog")
|
||||
end
|
||||
end
|
||||
|
||||
context "register_local_handler" do
|
||||
|
Loading…
Reference in New Issue
Block a user