changeset 6103:af16c135fb98

url's with javascript scheme should not be links in reST A javascript url in a reStructuredText document should not be displayed as a link. So: javascript:nastyJavascriptCode should be displayed as text and not a link. We do this by stripping the scheme from the schemes array in docutils.utils.urischemes. We set a property on the StringHTMLProperty to hold the list of schemes we want to disable so the user can choose to change it if they want.
author John Rouillard <rouilj@ieee.org>
date Tue, 25 Feb 2020 22:48:17 -0500
parents 0a82437a2930
children a1fd9551d416
files roundup/cgi/templating.py test/test_templating.py
diffstat 2 files changed, 32 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/roundup/cgi/templating.py	Tue Feb 25 16:36:18 2020 +0000
+++ b/roundup/cgi/templating.py	Tue Feb 25 22:48:17 2020 -0500
@@ -1499,6 +1499,12 @@
                     'raw_enabled': 0,
                     '_disable_config': 1}
 
+    # List of schemes that are not rendered as links in rst. 
+    # Could also be used to disable links for other processors:
+    # e.g. stext or markdown. If we can figure out how to do it.
+    disable_schemes = [ 'javascript' ]
+    valid_schemes = { }
+
     def _hyper_repl(self, match):
         if match.group('url'):
             return self._hyper_repl_url(match, '<a href="%s" rel="nofollow noopener">%s</a>%s')
@@ -1661,6 +1667,27 @@
         s = self.plain(escape=0, hyperlink=0)
         if hyperlink:
             s = self.hyper_re.sub(self._hyper_repl_rst, s)
+
+        # disable javascript and possibly other url schemes from working
+        from docutils.utils.urischemes import schemes
+        for sch in self.disable_schemes:
+            # I catch KeyError but reraise if scheme didn't exist.
+            # Safer to fail if a disabled scheme isn't found. It may
+            # be a typo that keeps a bad scheme enabled. But this
+            # function can be called multiple times. On the first call
+            # the key will be deleted. On the second call the schemes
+            # variable isn't re-initialized so the key is missing
+            # causing a KeyError. So see if we removed it (and entered
+            # it into valid_schemes). If we didn't raise KeyError.
+            try:
+                del(schemes[sch])
+                self.valid_schemes[sch] = True
+            except KeyError:
+                if sch in self.valid_schemes:
+                    pass
+                else:
+                    raise
+                
         return u2s(ReStructuredText(s, writer_name="html",
                        settings_overrides=self.rst_defaults)["html_body"])
 
--- a/test/test_templating.py	Tue Feb 25 16:36:18 2020 +0000
+++ b/test/test_templating.py	Tue Feb 25 22:48:17 2020 -0500
@@ -281,9 +281,14 @@
 </div>
 </div>
 '''
+	# test case to make sure javascript url's aren't turned into links
+        s = StringHTMLProperty(self.client, 'test', '1', None, 'test', u2s(u'<badtag>\njavascript:badcode'))
+        s_result = '<div class="document">\n<p>&lt;badtag&gt;\njavascript:badcode</p>\n</div>\n'
+
         self.assertEqual(p.rst(), u2s(u'<div class="document">\n<p>A string with <a class="reference external" href="mailto:cmeerw&#64;example.com">cmeerw&#64;example.com</a> <em>embedded</em> \u00df</p>\n</div>\n'))
         self.assertEqual(q.rst(), u2s(q_result))
         self.assertEqual(r.rst(), u2s(r_result))
+        self.assertEqual(s.rst(), u2s(s_result))
 
     @skip_stext
     def test_string_stext(self):

Roundup Issue Tracker: http://roundup-tracker.org/