allura-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brond...@apache.org
Subject [2/8] allura git commit: [#7887] ticket:790 Allow html in error messages, but escape them by default anyway
Date Thu, 04 Jun 2015 21:27:23 GMT
[#7887] ticket:790 Allow html in error messages, but escape them by default anyway

This is useful for custom messages. E.g. you can extend NexmoPhoneService with
custom errors which will include html by using jinja2.Markup to mark them as
safe, so that escaping will not take effect. By default all messages received
from nexmo are escaped.


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/bc064d87
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/bc064d87
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/bc064d87

Branch: refs/heads/master
Commit: bc064d8712d40f13df3a4642ec9a2fa05023ebdb
Parents: 55a1aaa
Author: Igor Bondarenko <jetmind2@gmail.com>
Authored: Thu Jun 4 08:30:38 2015 +0000
Committer: Igor Bondarenko <jetmind2@gmail.com>
Committed: Thu Jun 4 08:30:38 2015 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/project.py            |  7 +++++
 .../allura/public/nf/js/phone-verification.js   |  8 ++++--
 .../tests/functional/test_neighborhood.py       | 28 ++++++++++++++++++++
 3 files changed, 41 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/bc064d87/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 197f859..2f6d9be 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -27,6 +27,7 @@ from tg.decorators import with_trailing_slash, without_trailing_slash
 from pylons import tmpl_context as c, app_globals as g
 from paste.deploy.converters import asbool
 from webob import exc
+import jinja2
 import pymongo
 from formencode.api import Invalid
 
@@ -206,6 +207,9 @@ class NeighborhoodController(object):
             number_hash = utils.phone_number_hash(number)
             session['phone_verification.number_hash'] = number_hash
             session.save()
+        if 'error' in result:
+            result['error'] = jinja2.Markup.escape(result['error'])
+            result['error'] = h.really_unicode(result['error'])
         return result
 
     @expose('json:')
@@ -214,6 +218,9 @@ class NeighborhoodController(object):
         request_id = session.get('phone_verification.request_id')
         number_hash = session.get('phone_verification.number_hash')
         res = p.check_phone_verification(c.user, request_id, pin, number_hash)
+        if 'error' in res:
+            res['error'] = jinja2.Markup.escape(res['error'])
+            res['error'] = h.really_unicode(res['error'])
         return res
 
     @expose('json:')

http://git-wip-us.apache.org/repos/asf/allura/blob/bc064d87/Allura/allura/public/nf/js/phone-verification.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/phone-verification.js b/Allura/allura/public/nf/js/phone-verification.js
index e6bb8fc..1a22c83 100644
--- a/Allura/allura/public/nf/js/phone-verification.js
+++ b/Allura/allura/public/nf/js/phone-verification.js
@@ -70,14 +70,18 @@ var FormStepMixin = {
       onClick: this.handleClick,
       disabled: this.isButtonDisabled()
     };
-    var nbsp = String.fromCharCode(160);
     return dom('div', null,
              dom('label', {className: grid}, this.getLabel()),
              dom('input', input_props),
-             dom('div', {className: grid + ' error-text'}, this.props.state.error || nbsp),
+             dom('div', {className: grid + ' error-text',
+                         dangerouslySetInnerHTML: this.getErrorHtml()}),
              dom('div', {className: grid},
                dom('button', button_props, 'Submit')));
   },
+
+  getErrorHtml: function() {
+    return {__html: this.props.state.error || '&nbsp;'};
+  },
   
   handleClick: function() {
     if (!this.isButtonDisabled()) {

http://git-wip-us.apache.org/repos/asf/allura/blob/bc064d87/Allura/allura/tests/functional/test_neighborhood.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index b3ab279..593671d 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -992,6 +992,20 @@ class TestPhoneVerificationOnProjectRegistration(TestController):
             assert_equal(rid, 'request-id')
             assert_equal(hash, 'f9ac49faef45d18746ced08d001e23b179107940')
 
+    @patch.object(g, 'phone_service', autospec=True)
+    def test_verify_phone_escapes_error(self, phone_service):
+        phone_service.verify.return_value = {
+            'status': 'error',
+            'error': '<script>alert("hacked");</script>',
+        }
+        with h.push_config(config, **{'project.verify_phone': 'true'}):
+            r = self.app.get('/p/verify_phone', {'number': '555-444-3333'})
+        expected = {
+            'status': 'error',
+            'error': u'&lt;script&gt;alert(&#34;hacked&#34;);&lt;/script&gt;',
+        }
+        assert_equal(r.json, expected)
+
     def test_check_phone_verification_no_params(self):
         with h.push_config(config, **{'project.verify_phone': 'true'}):
             self.app.get('/p/check_phone_verification', status=404)
@@ -1034,6 +1048,20 @@ class TestPhoneVerificationOnProjectRegistration(TestController):
             hash = user.get_tool_data('phone_verification', 'number_hash')
             assert_equal(hash, '54c61c96d5d5aea5254c2d4f41508a938e5501b4')
 
+    @patch.object(g, 'phone_service', autospec=True)
+    def test_check_phone_verification_escapes_error(self, phone_service):
+        phone_service.check.return_value = {
+            'status': 'error',
+            'error': '<script>alert("hacked");</script>',
+        }
+        with h.push_config(config, **{'project.verify_phone': 'true'}):
+            r = self.app.get('/p/check_phone_verification', {'pin': '1234'})
+        expected = {
+            'status': 'error',
+            'error': u'&lt;script&gt;alert(&#34;hacked&#34;);&lt;/script&gt;',
+        }
+        assert_equal(r.json, expected)
+
     def test_register_phone_not_verified(self):
         with h.push_config(config, **{'project.verify_phone': 'true'}):
             r = self.app.post(


Mime
View raw message