Skip to content

Commit ed3caee

Browse files
author
Richard Jones
committed
fix hackish message escaping [SF#757128]
1 parent 36ad8fd commit ed3caee

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ are given with the most recent entry first.
66
- handle deprecation of FCNTL in python2.2+ (sf bug 756756)
77
- handle missing Subject: line (sf bug 755331)
88
- handle New User creation (sf bug 754510)
9+
- fix hackish message escaping (sf bug 757128)
910

1011

1112
2003-06-10 0.6.0b3

roundup/cgi/client.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: client.py,v 1.119 2003-06-10 22:55:30 richard Exp $
1+
# $Id: client.py,v 1.120 2003-06-24 03:30:30 richard Exp $
22

33
__doc__ = """
44
WWW request handler (also used in the stand-alone server).
@@ -68,10 +68,16 @@ def initialiseSecurity(security):
6868
description="User may manipulate user Roles through the web")
6969
security.addPermissionToRole('Admin', p)
7070

71-
def clean_message(match, ok={'a':1,'i':1,'b':1,'br':1}):
71+
# used to clean messages passed through CGI variables - HTML-escape any tag
72+
# that isn't <a href="">, <i>, <b> and <br> (including XHTML variants) so
73+
# that people can't pass through nasties like <script>, <iframe>, ...
74+
CLEAN_MESSAGE_RE = r'(<(/?(.*?)(\s*href="[^"]")?\s*/?)>)'
75+
def clean_message(message, mc=re.compile(CLEAN_MESSAGE_RE, re.I)):
76+
return mc.sub(clean_message_callback, message)
77+
def clean_message_callback(match, ok={'a':1,'i':1,'b':1,'br':1}):
7278
''' Strip all non <a>,<i>,<b> and <br> tags from a string
7379
'''
74-
if ok.has_key(match.group(2)):
80+
if ok.has_key(match.group(3).lower()):
7581
return match.group(1)
7682
return '&lt;%s&gt;'%match.group(2)
7783

@@ -348,8 +354,7 @@ def determine_user(self):
348354
# reopen the database as the correct user
349355
self.opendb(self.user)
350356

351-
def determine_context(self, dre=re.compile(r'([^\d]+)(\d+)'),
352-
mc=re.compile(r'(</?(.*?)>)')):
357+
def determine_context(self, dre=re.compile(r'([^\d]+)(\d+)')):
353358
''' Determine the context of this page from the URL:
354359
355360
The URL path after the instance identifier is examined. The path
@@ -397,10 +402,10 @@ def determine_context(self, dre=re.compile(r'([^\d]+)(\d+)'),
397402
template_override = self.form[key].value
398403
elif self.FV_OK_MESSAGE.match(key):
399404
ok_message = self.form[key].value
400-
ok_message = mc.sub(clean_message, ok_message)
405+
ok_message = clean_message(ok_message)
401406
elif self.FV_ERROR_MESSAGE.match(key):
402407
error_message = self.form[key].value
403-
error_message = mc.sub(clean_message, error_message)
408+
error_message = clean_message(error_message)
404409

405410
# determine the classname and possibly nodeid
406411
path = self.path.split('/')

test/test_cgi.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# but WITHOUT ANY WARRANTY; without even the implied warranty of
99
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1010
#
11-
# $Id: test_cgi.py,v 1.16 2003-05-09 01:47:50 richard Exp $
11+
# $Id: test_cgi.py,v 1.17 2003-06-24 03:30:40 richard Exp $
1212

1313
import unittest, os, shutil, errno, sys, difflib, cgi, re
1414

@@ -37,6 +37,26 @@ class config:
3737
TRACKER_NAME = 'testing testing'
3838
TRACKER_WEB = 'http://testing.testing/'
3939

40+
cm = client.clean_message
41+
class MessageTestCase(unittest.TestCase):
42+
def testCleanMessageOK(self):
43+
self.assertEqual(cm('<br>x<br />'), '<br>x<br />')
44+
self.assertEqual(cm('<i>x</i>'), '<i>x</i>')
45+
self.assertEqual(cm('<b>x</b>'), '<b>x</b>')
46+
self.assertEqual(cm('<a href="y">x</a>'),
47+
'<a href="y">x</a>')
48+
self.assertEqual(cm('<BR>x<BR />'), '<BR>x<BR />')
49+
self.assertEqual(cm('<I>x</I>'), '<I>x</I>')
50+
self.assertEqual(cm('<B>x</B>'), '<B>x</B>')
51+
self.assertEqual(cm('<A HREF="y">x</A>'),
52+
'<A HREF="y">x</A>')
53+
54+
def testCleanMessageBAD(self):
55+
self.assertEqual(cm('<script>x</script>'),
56+
'&lt;script&gt;x&lt;/script&gt;')
57+
self.assertEqual(cm('<iframe>x</iframe>'),
58+
'&lt;iframe&gt;x&lt;/iframe&gt;')
59+
4060
class FormTestCase(unittest.TestCase):
4161
def setUp(self):
4262
self.dirname = '_test_cgi_form'
@@ -502,7 +522,9 @@ def testBackwardsCompat(self):
502522
[('issue', None, 'files', [('file', '-1')])]))
503523

504524
def suite():
505-
l = [unittest.makeSuite(FormTestCase),
525+
l = [
526+
unittest.makeSuite(FormTestCase),
527+
unittest.makeSuite(MessageTestCase),
506528
]
507529
return unittest.TestSuite(l)
508530

0 commit comments

Comments
 (0)