Mercurial > p > roundup > code
comparison test/test_actions.py @ 4880:ca692423e401
Different approach to fix XSS in issue2550817
Encapsulate the error/ok message append method as add_ok_message and
add_error_message. The new approach escapes the messages when appending
-- at a point in the code where we still know where the message comes
from. Escaping is the default but can bei turned off. This also fixes
issue2550836 where certain messages may contain links.
Another advantage of the new fix is that users don't need to change
installed trackers and are secure by default.
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Mon, 31 Mar 2014 18:19:23 +0200 |
| parents | 9cc6d463cfbe |
| children | b562df8a5056 |
comparison
equal
deleted
inserted
replaced
| 4879:302c967d710c | 4880:ca692423e401 |
|---|---|
| 2 from cgi import FieldStorage, MiniFieldStorage | 2 from cgi import FieldStorage, MiniFieldStorage |
| 3 | 3 |
| 4 from roundup import hyperdb | 4 from roundup import hyperdb |
| 5 from roundup.date import Date, Interval | 5 from roundup.date import Date, Interval |
| 6 from roundup.cgi.actions import * | 6 from roundup.cgi.actions import * |
| 7 from roundup.cgi.client import add_message | |
| 7 from roundup.cgi.exceptions import Redirect, Unauthorised, SeriousError | 8 from roundup.cgi.exceptions import Redirect, Unauthorised, SeriousError |
| 8 | 9 |
| 9 from mocknull import MockNull | 10 from mocknull import MockNull |
| 10 | 11 |
| 11 def true(*args, **kwargs): | 12 def true(*args, **kwargs): |
| 13 | 14 |
| 14 class ActionTestCase(unittest.TestCase): | 15 class ActionTestCase(unittest.TestCase): |
| 15 def setUp(self): | 16 def setUp(self): |
| 16 self.form = FieldStorage() | 17 self.form = FieldStorage() |
| 17 self.client = MockNull() | 18 self.client = MockNull() |
| 19 self.client._ok_message = [] | |
| 20 self.client._error_message = [] | |
| 21 self.client.add_error_message = lambda x : add_message( | |
| 22 self.client._error_message, x) | |
| 23 self.client.add_ok_message = lambda x : add_message( | |
| 24 self.client._ok_message, x) | |
| 18 self.client.form = self.form | 25 self.client.form = self.form |
| 19 class TemplatingUtils: | 26 class TemplatingUtils: |
| 20 pass | 27 pass |
| 21 self.client.instance.interfaces.TemplatingUtils = TemplatingUtils | 28 self.client.instance.interfaces.TemplatingUtils = TemplatingUtils |
| 22 | 29 |
| 58 'No type specified') | 65 'No type specified') |
| 59 | 66 |
| 60 class RetireActionTestCase(ActionTestCase): | 67 class RetireActionTestCase(ActionTestCase): |
| 61 def testRetireAction(self): | 68 def testRetireAction(self): |
| 62 self.client.db.security.hasPermission = true | 69 self.client.db.security.hasPermission = true |
| 63 self.client.ok_message = [] | 70 self.client._ok_message = [] |
| 64 RetireAction(self.client).handle() | 71 RetireAction(self.client).handle() |
| 65 self.assert_(len(self.client.ok_message) == 1) | 72 self.assert_(len(self.client._ok_message) == 1) |
| 66 | 73 |
| 67 def testNoPermission(self): | 74 def testNoPermission(self): |
| 68 self.assertRaises(Unauthorised, RetireAction(self.client).execute) | 75 self.assertRaises(Unauthorised, RetireAction(self.client).execute) |
| 69 | 76 |
| 70 def testDontRetireAdminOrAnonymous(self): | 77 def testDontRetireAdminOrAnonymous(self): |
| 177 self.failIf(self.action.detectCollision(None, self.now)) | 184 self.failIf(self.action.detectCollision(None, self.now)) |
| 178 | 185 |
| 179 class LoginTestCase(ActionTestCase): | 186 class LoginTestCase(ActionTestCase): |
| 180 def setUp(self): | 187 def setUp(self): |
| 181 ActionTestCase.setUp(self) | 188 ActionTestCase.setUp(self) |
| 182 self.client.error_message = [] | 189 self.client._error_message = [] |
| 183 | 190 |
| 184 # set the db password to 'right' | 191 # set the db password to 'right' |
| 185 self.client.db.user.get = lambda a,b: 'right' | 192 self.client.db.user.get = lambda a,b: 'right' |
| 186 | 193 |
| 187 # unless explicitly overridden, we should never get here | 194 # unless explicitly overridden, we should never get here |
| 194 if password is not None: | 201 if password is not None: |
| 195 self.form.value.append( | 202 self.form.value.append( |
| 196 MiniFieldStorage('__login_password', password)) | 203 MiniFieldStorage('__login_password', password)) |
| 197 | 204 |
| 198 LoginAction(self.client).handle() | 205 LoginAction(self.client).handle() |
| 199 self.assertEqual(self.client.error_message, messages) | 206 self.assertEqual(self.client._error_message, messages) |
| 200 | 207 |
| 201 def testNoUsername(self): | 208 def testNoUsername(self): |
| 202 self.assertLoginLeavesMessages(['Username required']) | 209 self.assertLoginLeavesMessages(['Username required']) |
| 203 | 210 |
| 204 def testInvalidUsername(self): | 211 def testInvalidUsername(self): |
