Skip to content

Commit

Permalink
Merge pull request #513 from Crozzers/fix-rel-links-in-safe-mode
Browse files Browse the repository at this point in the history
Fix relative links not working in safe mode (issue #254)
  • Loading branch information
nicholasserra committed Jun 4, 2023
2 parents 2c092d1 + 4a46040 commit cef18e1
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -9,6 +9,7 @@
- [pull #509] Fix HTML elements not unhashing correctly (issue 508)
- [pull #511] Remove deprecated `imp` module (issue #510)
- [pull #512] Allow link patterns to be passed via extras dict
- [pull #513] Fix relative links not working in safe mode (issue #254)


## python-markdown2 2.4.8
Expand Down
12 changes: 9 additions & 3 deletions lib/markdown2.py
Expand Up @@ -1483,7 +1483,13 @@ def _protect_url(self, url):
self._escape_table[url] = key
return key

_safe_protocols = re.compile(r'(https?|ftp):', re.I)
# _safe_href is copied from pagedown's Markdown.Sanitizer.js
# From: https://github.com/StackExchange/pagedown/blob/master/LICENSE.txt
# Original Showdown code copyright (c) 2007 John Fraser
# Modifications and bugfixes (c) 2009 Dana Robinson
# Modifications and bugfixes (c) 2009-2014 Stack Exchange Inc.
_safe_href = re.compile(r'^((https?|ftp):\/\/|\/|\.|#)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)*[\]$]*$', re.I)

def _do_links(self, text):
"""Turn Markdown link shortcuts into XHTML <a> and <img> tags.
Expand Down Expand Up @@ -1601,7 +1607,7 @@ def _do_links(self, text):
anchor_allowed_pos = start_idx + len(result)
text = text[:start_idx] + result + text[url_end_idx:]
elif start_idx >= anchor_allowed_pos:
safe_link = self._safe_protocols.match(url) or url.startswith('#')
safe_link = self._safe_href.match(url)
if self.safe_mode and not safe_link:
result_head = '<a href="#"%s>' % (title_str)
else:
Expand Down Expand Up @@ -1657,7 +1663,7 @@ def _do_links(self, text):
curr_pos = start_idx + len(result)
text = text[:start_idx] + result + text[match.end():]
elif start_idx >= anchor_allowed_pos:
if self.safe_mode and not self._safe_protocols.match(url):
if self.safe_mode and not self._safe_href.match(url):
result_head = '<a href="#"%s>' % (title_str)
else:
result_head = '<a href="%s"%s>' % (self._protect_url(url), title_str)
Expand Down
6 changes: 3 additions & 3 deletions test/tm-cases/basic_safe_mode.html
Expand Up @@ -6,13 +6,13 @@

<p>[HTML_REMOVED]alert(1)[HTML_REMOVED]</p>

<p><a href="http://example.com&quot;onclick=&quot;alert(1)">link1</a></p>
<p><a href="#">link1</a></p>

<p><a href="http://example.com" title="title&quot;onclick=&quot;alert(1)">link2</a></p>

<p><a href="http://example.com&gt;[HTML_REMOVED]alert(1)[HTML_REMOVED]">link3</a></p>
<p><a href="#">link3</a></p>

<p><a href="http://example.com&gt;[HTML_REMOVED]alert(1)[HTML_REMOVED]">link4 &gt;[HTML_REMOVED]alert(1)[HTML_REMOVED]</a></p>
<p><a href="#">link4 &gt;[HTML_REMOVED]alert(1)[HTML_REMOVED]</a></p>

<p><a href="#">link5</a></p>

Expand Down
6 changes: 6 additions & 0 deletions test/tm-cases/relative_links_safe_mode.html
@@ -0,0 +1,6 @@
<p><a href="https://www.hostname.com/absolute/path">link1</a>
<a href="https://www.hostname.com/absolute/path#anchor-on-another-page">link2</a>
<a href="#anchor-on-this-page">link3</a>
<a href="/">link4</a>
<a href="/absolute/path">link5</a>
<a href="../relative/path">link6</a></p>
1 change: 1 addition & 0 deletions test/tm-cases/relative_links_safe_mode.opts
@@ -0,0 +1 @@
{"safe_mode": "escape"}
6 changes: 6 additions & 0 deletions test/tm-cases/relative_links_safe_mode.text
@@ -0,0 +1,6 @@
[link1](https://www.hostname.com/absolute/path)
[link2](https://www.hostname.com/absolute/path#anchor-on-another-page)
[link3](#anchor-on-this-page)
[link4](/)
[link5](/absolute/path)
[link6](../relative/path)

0 comments on commit cef18e1

Please sign in to comment.