Skip to content

Commit 1b5ca22

Browse files
committed
Fix rendering <a> without href when scheme unsupported
- Disallow links with relative paths - Disallow iframes with non-http protocols and relative paths Close #13037
1 parent aeb6efb commit 1b5ca22

2 files changed

Lines changed: 55 additions & 6 deletions

File tree

app/lib/sanitize_config.rb

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,23 @@
22

33
class Sanitize
44
module Config
5-
HTTP_PROTOCOLS ||= ['http', 'https', 'dat', 'dweb', 'ipfs', 'ipns', 'ssb', 'gopher', 'xmpp', 'magnet', :relative].freeze
5+
HTTP_PROTOCOLS = %w(
6+
http
7+
https
8+
).freeze
9+
10+
LINK_PROTOCOLS = %w(
11+
http
12+
https
13+
dat
14+
dweb
15+
ipfs
16+
ipns
17+
ssb
18+
gopher
19+
xmpp
20+
magnet
21+
).freeze
622

723
CLASS_WHITELIST_TRANSFORMER = lambda do |env|
824
node = env[:node]
@@ -19,19 +35,37 @@ module Config
1935
node['class'] = class_list.join(' ')
2036
end
2137

38+
UNSUPPORTED_HREF_TRANSFORMER = lambda do |env|
39+
return unless env[:node_name] == 'a'
40+
41+
current_node = env[:node]
42+
43+
scheme = begin
44+
if current_node['href'] =~ Sanitize::REGEX_PROTOCOL
45+
Regexp.last_match(1).downcase
46+
else
47+
:relative
48+
end
49+
end
50+
51+
current_node.replace(current_node.text) unless LINK_PROTOCOLS.include?(scheme)
52+
end
53+
2254
UNSUPPORTED_ELEMENTS_TRANSFORMER = lambda do |env|
2355
return unless %w(h1 h2 h3 h4 h5 h6 blockquote pre ul ol li).include?(env[:node_name])
2456

57+
current_node = env[:node]
58+
2559
case env[:node_name]
2660
when 'li'
27-
env[:node].traverse do |node|
61+
current_node.traverse do |node|
2862
next unless %w(p ul ol li).include?(node.name)
2963

3064
node.add_next_sibling('<br>') if node.next_sibling
3165
node.replace(node.children) unless node.text?
3266
end
3367
else
34-
env[:node].name = 'p'
68+
current_node.name = 'p'
3569
end
3670
end
3771

@@ -50,13 +84,12 @@ module Config
5084
},
5185
},
5286

53-
protocols: {
54-
'a' => { 'href' => HTTP_PROTOCOLS },
55-
},
87+
protocols: {},
5688

5789
transformers: [
5890
CLASS_WHITELIST_TRANSFORMER,
5991
UNSUPPORTED_ELEMENTS_TRANSFORMER,
92+
UNSUPPORTED_HREF_TRANSFORMER,
6093
]
6194
)
6295

spec/lib/sanitize_config_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,21 @@
2626
it 'keep links in lists' do
2727
expect(Sanitize.fragment('<p>Check out:</p><ul><li><a href="https://joinmastodon.org" rel="nofollow noopener noreferrer" target="_blank">joinmastodon.org</a></li><li>Bar</li></ul>', subject)).to eq '<p>Check out:</p><p><a href="https://joinmastodon.org" rel="nofollow noopener noreferrer" target="_blank">joinmastodon.org</a><br>Bar</p>'
2828
end
29+
30+
it 'removes a without href' do
31+
expect(Sanitize.fragment('<a>Test</a>', subject)).to eq 'Test'
32+
end
33+
34+
it 'removes a without href and only keeps text content' do
35+
expect(Sanitize.fragment('<a><span class="invisible">foo&amp;</span><span>Test</span></a>', subject)).to eq 'foo&amp;Test'
36+
end
37+
38+
it 'removes a with unsupported scheme in href' do
39+
expect(Sanitize.fragment('<a href="foo://bar">Test</a>', subject)).to eq 'Test'
40+
end
41+
42+
it 'keeps a with href' do
43+
expect(Sanitize.fragment('<a href="http://example.com">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
44+
end
2945
end
3046
end

0 commit comments

Comments
 (0)