Commit a64d9268 by Ned Batchelder

Merge pull request #7399 from edx/ned/plat-462

Make sure slashes in JSON content don't end script tags. PLAT-462
parents e03813da 6928035c
...@@ -113,11 +113,10 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer, ...@@ -113,11 +113,10 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer,
} }
if hasattr(frag, 'json_init_args') and frag.json_init_args is not None: if hasattr(frag, 'json_init_args') and frag.json_init_args is not None:
template_context['js_init_parameters'] = json.dumps(frag.json_init_args) # Replace / with \/ so that "</script>" in the data won't break things.
template_context['js_pass_parameters'] = True template_context['js_init_parameters'] = json.dumps(frag.json_init_args).replace("/", r"\/")
else: else:
template_context['js_init_parameters'] = "" template_context['js_init_parameters'] = ""
template_context['js_pass_parameters'] = False
return wrap_fragment(frag, render_to_string('xblock_wrapper.html', template_context)) return wrap_fragment(frag, render_to_string('xblock_wrapper.html', template_context))
......
<div class="${' '.join(classes) | n}" ${data_attributes}> <div class="${' '.join(classes) | n}" ${data_attributes}>
% if js_pass_parameters: % if js_init_parameters:
<script type="json/xblock-args" class="xblock_json_init_args"> <script type="json/xblock-args" class="xblock_json_init_args">
${js_init_parameters} ${js_init_parameters}
</script> </script>
......
...@@ -16,10 +16,12 @@ from django.contrib.auth.models import AnonymousUser ...@@ -16,10 +16,12 @@ from django.contrib.auth.models import AnonymousUser
from mock import MagicMock, patch, Mock from mock import MagicMock, patch, Mock
from opaque_keys.edx.keys import UsageKey, CourseKey from opaque_keys.edx.keys import UsageKey, CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey
from courseware.module_render import hash_resource
from xblock.field_data import FieldData from xblock.field_data import FieldData
from xblock.runtime import Runtime from xblock.runtime import Runtime
from xblock.fields import ScopeIds from xblock.fields import ScopeIds
from xblock.core import XBlock from xblock.core import XBlock
from xblock.fragment import Fragment
from capa.tests.response_xml_factory import OptionResponseXMLFactory from capa.tests.response_xml_factory import OptionResponseXMLFactory
from courseware import module_render as render from courseware import module_render as render
...@@ -660,6 +662,53 @@ class TestHtmlModifiers(ModuleStoreTestCase): ...@@ -660,6 +662,53 @@ class TestHtmlModifiers(ModuleStoreTestCase):
) )
class XBlockWithJsonInitData(XBlock):
"""
Pure XBlock to use in tests, with JSON init data.
"""
the_json_data = None
def student_view(self, context=None): # pylint: disable=unused-argument
"""
A simple view that returns just enough to test.
"""
frag = Fragment(u"Hello there!")
frag.add_javascript(u'alert("Hi!");')
frag.initialize_js('ThumbsBlock', self.the_json_data)
return frag
@ddt.ddt
class JsonInitDataTest(ModuleStoreTestCase):
"""Tests for JSON data injected into the JS init function."""
@ddt.data(
({'a': 17}, '''{"a": 17}'''),
({'xss': '</script>alert("XSS")'}, r'''{"xss": "<\/script>alert(\"XSS\")"}'''),
)
@ddt.unpack
@XBlock.register_temp_plugin(XBlockWithJsonInitData, identifier='withjson')
def test_json_init_data(self, json_data, json_output):
XBlockWithJsonInitData.the_json_data = json_data
mock_user = UserFactory()
mock_request = MagicMock()
mock_request.user = mock_user
course = CourseFactory()
descriptor = ItemFactory(category='withjson', parent=course)
field_data_cache = FieldDataCache([course, descriptor], course.id, mock_user) # pylint: disable=no-member
module = render.get_module_for_descriptor(
mock_user,
mock_request,
descriptor,
field_data_cache,
course.id, # pylint: disable=no-member
)
html = module.render(STUDENT_VIEW).content
self.assertIn(json_output, html)
# No matter what data goes in, there should only be one close-script tag.
self.assertEqual(html.count("</script>"), 1)
class ViewInStudioTest(ModuleStoreTestCase): class ViewInStudioTest(ModuleStoreTestCase):
"""Tests for the 'View in Studio' link visiblity.""" """Tests for the 'View in Studio' link visiblity."""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment