Escape untrusted content before displaying it.

Reviewed in https://codereview.appspot.com/6460120/.
This commit is contained in:
Joe Gregorio
2012-08-27 14:13:22 -04:00
parent 0fd1853b95
commit 77254c102d
2 changed files with 23 additions and 7 deletions

View File

@@ -20,6 +20,7 @@ Utilities for making it easier to use OAuth 2.0 on Google App Engine.
__author__ = 'jcgregorio@google.com (Joe Gregorio)'
import base64
import cgi
import httplib2
import logging
import os
@@ -51,6 +52,18 @@ OAUTH2CLIENT_NAMESPACE = 'oauth2client#ns'
XSRF_MEMCACHE_ID = 'xsrf_secret_key'
def _safe_html(s):
"""Escape text to make it safe to display.
Args:
s: string, The text to escape.
Returns:
The escaped text as a string.
"""
return cgi.escape(s, quote=1).replace("'", ''')
class InvalidClientSecretsError(Exception):
"""The client_secrets.json file is malformed or missing required fields."""
@@ -417,7 +430,7 @@ class OAuth2Decorator(object):
def _display_error_message(self, request_handler):
request_handler.response.out.write('<html><body>')
request_handler.response.out.write(self._message)
request_handler.response.out.write(_safe_html(self._message))
request_handler.response.out.write('</body></html>')
def oauth_required(self, method):
@@ -578,7 +591,7 @@ class OAuth2Decorator(object):
if error:
errormsg = self.request.get('error_description', error)
self.response.out.write(
'The authorization request failed: %s' % errormsg)
'The authorization request failed: %s' % _safe_html(errormsg))
else:
user = users.get_current_user()
decorator._create_flow(self)

View File

@@ -331,7 +331,10 @@ class DecoratorTests(unittest.TestCase):
webapp2.Route(r'/bar_path/<year:\d{4}>/<month:\d{2}>',
handler=TestAwareHandler, name='bar')],
debug=True)
self.app = TestApp(application)
self.app = TestApp(application, extra_environ={
'wsgi.url_scheme': 'http',
'HTTP_HOST': 'localhost',
})
users.get_current_user = user_mock()
self.httplib2_orig = httplib2.Http
httplib2.Http = Http2Mock
@@ -343,7 +346,7 @@ class DecoratorTests(unittest.TestCase):
def test_required(self):
# An initial request to an oauth_required decorated path should be a
# redirect to start the OAuth dance.
response = self.app.get('/foo_path')
response = self.app.get('http://localhost/foo_path')
self.assertTrue(response.status.startswith('302'))
q = parse_qs(response.headers['Location'].split('?', 1)[1])
self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0])
@@ -425,7 +428,7 @@ class DecoratorTests(unittest.TestCase):
def test_aware(self):
# An initial request to an oauth_aware decorated path should not redirect.
response = self.app.get('/bar_path/2012/01')
response = self.app.get('http://localhost/bar_path/2012/01')
self.assertEqual('Hello World!', response.body)
self.assertEqual('200 OK', response.status)
self.assertEqual(False, self.decorator.has_credentials())
@@ -471,10 +474,10 @@ class DecoratorTests(unittest.TestCase):
response = self.app.get('/bar_path/2012/01')
url = self.decorator.authorize_url()
response = self.app.get('/oauth2callback', {
'error': 'BadStuffHappened'
'error': 'Bad<Stuff>Happened\''
})
self.assertEqual('200 OK', response.status)
self.assertTrue('BadStuffHappened' in response.body)
self.assertTrue('Bad&lt;Stuff&gt;Happened&#39;' in response.body)
def test_kwargs_are_passed_to_underlying_flow(self):
decorator = OAuth2Decorator(client_id='foo_client_id',