Michael Merickel
2015-04-29 560ec837d9f68b0b9c1ae3f8f742b5a7de6f6d23
Merge pull request #1648 from Pylons/1.5-fix-jsonp

backport jsonp fixes from master
3 files modified
30 ■■■■ changed files
CHANGES.txt 11 ●●●●● patch | view | raw | blame | history
pyramid/renderers.py 7 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_renderers.py 12 ●●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -1,3 +1,14 @@
unreleased
==========
- Further fix the JSONP renderer by prefixing the returned content with
  a comment. This should mitigate attacks from Flash (See CVE-2014-4671).
  See https://github.com/Pylons/pyramid/pull/1648
- Allow periods and brackets (``[]``) in the JSONP callback. The original
  fix was overly-restrictive and broke Angular.
  See https://github.com/Pylons/pyramid/pull/1648
.. _changes_1.5.6:
1.5.6 (2015-04-14)
pyramid/renderers.py
@@ -286,7 +286,7 @@
json_renderer_factory = JSON() # bw compat
JSONP_VALID_CALLBACK = re.compile(r"^[a-zA-Z_$][0-9a-zA-Z_$]+$")
JSONP_VALID_CALLBACK = re.compile(r"^[$a-z_][$0-9a-z_\.\[\]]+[^.]$", re.I)
class JSONP(JSON):
    """ `JSONP <http://en.wikipedia.org/wiki/JSONP>`_ renderer factory helper
@@ -371,10 +371,11 @@
                if callback is not None:
                    if not JSONP_VALID_CALLBACK.match(callback):
                        raise HTTPBadRequest('Invalid JSONP callback function name.')
                        raise HTTPBadRequest(
                            'Invalid JSONP callback function name.')
                    ct = 'application/javascript'
                    body = '%s(%s);' % (callback, val)
                    body = '/**/{0}({1});'.format(callback, val)
                response = request.response
                if response.content_type == response.default_content_type:
                    response.content_type = ct
pyramid/tests/test_renderers.py
@@ -567,7 +567,17 @@
        request = testing.DummyRequest()
        request.GET['callback'] = 'callback'
        result = renderer({'a':'1'}, {'request':request})
        self.assertEqual(result, 'callback({"a": "1"});')
        self.assertEqual(result, '/**/callback({"a": "1"});')
        self.assertEqual(request.response.content_type,
                         'application/javascript')
    def test_render_to_jsonp_with_dot(self):
        renderer_factory = self._makeOne()
        renderer = renderer_factory(None)
        request = testing.DummyRequest()
        request.GET['callback'] = 'angular.callbacks._0'
        result = renderer({'a':'1'}, {'request':request})
        self.assertEqual(result, '/**/angular.callbacks._0({"a": "1"});')
        self.assertEqual(request.response.content_type,
                         'application/javascript')