Skip to content

Commit

Permalink
Merge pull request #1627 from bertjwregeer/security/jsonp
Browse files Browse the repository at this point in the history
Add some validation for the JSONP callback
  • Loading branch information
mmerickel committed Apr 20, 2015
2 parents dddf33c + b6ffe51 commit dfce4e0
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 0 deletions.
9 changes: 9 additions & 0 deletions pyramid/renderers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import contextlib
import json
import os
import re

from zope.interface import (
implementer,
Expand All @@ -23,6 +24,8 @@

from pyramid.events import BeforeRender

from pyramid.httpexceptions import HTTPBadRequest

from pyramid.path import caller_package

from pyramid.response import _get_response_factory
Expand Down Expand Up @@ -305,6 +308,8 @@ def default(obj):

json_renderer_factory = JSON() # bw compat

JSONP_VALID_CALLBACK = re.compile(r"^[a-zA-Z_$][0-9a-zA-Z_$]+$")

class JSONP(JSON):
""" `JSONP <http://en.wikipedia.org/wiki/JSONP>`_ renderer factory helper
which implements a hybrid json/jsonp renderer. JSONP is useful for
Expand Down Expand Up @@ -385,7 +390,11 @@ def _render(value, system):
body = val
if request is not None:
callback = request.GET.get(self.param_name)

if callback is not None:
if not JSONP_VALID_CALLBACK.match(callback):
raise HTTPBadRequest('Invalid JSONP callback function name.')

ct = 'application/javascript'
body = '%s(%s);' % (callback, val)
response = request.response
Expand Down
8 changes: 8 additions & 0 deletions pyramid/tests/test_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,14 @@ def test_render_without_request(self):
result = renderer({'a':'1'}, {})
self.assertEqual(result, '{"a": "1"}')

def test_render_to_jsonp_invalid_callback(self):
from pyramid.httpexceptions import HTTPBadRequest
renderer_factory = self._makeOne()
renderer = renderer_factory(None)
request = testing.DummyRequest()
request.GET['callback'] = '78mycallback'
self.assertRaises(HTTPBadRequest, renderer, {'a':'1'}, {'request':request})


class Dummy:
pass
Expand Down

0 comments on commit dfce4e0

Please sign in to comment.