Make sure slashes in JSON content don't end script tags. PLAT-462
The string "</script>" in JSON data would end the script element we're embedding the data in. To make sure the data doesn't disrupt the script, we escape the slash as \/ .
This commit is contained in:
@@ -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:
|
||||
template_context['js_init_parameters'] = json.dumps(frag.json_init_args)
|
||||
template_context['js_pass_parameters'] = True
|
||||
# Replace / with \/ so that "</script>" in the data won't break things.
|
||||
template_context['js_init_parameters'] = json.dumps(frag.json_init_args).replace("/", r"\/")
|
||||
else:
|
||||
template_context['js_init_parameters'] = ""
|
||||
template_context['js_pass_parameters'] = False
|
||||
|
||||
return wrap_fragment(frag, render_to_string('xblock_wrapper.html', template_context))
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<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">
|
||||
${js_init_parameters}
|
||||
</script>
|
||||
|
||||
@@ -16,10 +16,12 @@ from django.contrib.auth.models import AnonymousUser
|
||||
from mock import MagicMock, patch, Mock
|
||||
from opaque_keys.edx.keys import UsageKey, CourseKey
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from courseware.module_render import hash_resource
|
||||
from xblock.field_data import FieldData
|
||||
from xblock.runtime import Runtime
|
||||
from xblock.fields import ScopeIds
|
||||
from xblock.core import XBlock
|
||||
from xblock.fragment import Fragment
|
||||
|
||||
from capa.tests.response_xml_factory import OptionResponseXMLFactory
|
||||
from courseware import module_render as render
|
||||
@@ -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):
|
||||
"""Tests for the 'View in Studio' link visiblity."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user