VYPR
Moderate severityNVD Advisory· Published Aug 23, 2019· Updated Aug 5, 2024

CVE-2019-15486

CVE-2019-15486

Description

Django JS Reverse before 0.9.1 is vulnerable to cross-site scripting (XSS) via the js_reverse_inline template tag due to insufficient output escaping.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Django JS Reverse before 0.9.1 is vulnerable to cross-site scripting (XSS) via the js_reverse_inline template tag due to insufficient output escaping.

Vulnerability

Overview

The js_reverse_inline template tag in django-js-reverse before version 0.9.1 fails to properly escape user-controlled data when generating inline JavaScript. This allows an attacker to inject arbitrary HTML or JavaScript into the page. The fix introduced a _safe_json function that escapes <, >, and & characters and removed the |safe filter from the template, ensuring that data is safely rendered [1][4].

Exploitation

An attacker can exploit this vulnerability by controlling input that is included in the JavaScript output, such as URL parameters or other data processed by the tag. The attack does not require authentication if the attacker can influence the data passed to the template. The vulnerability is triggered when a template uses the js_reverse_inline tag, which outputs inline JavaScript directly into the HTML [1][4].

Impact

Successful exploitation leads to cross-site scripting (XSS), enabling an attacker to execute arbitrary JavaScript in the context of the victim's browser. This can result in theft of cookies, session tokens, or other sensitive information, as well as unauthorized actions performed on behalf of the user [1].

Mitigation

The vulnerability is fixed in version 0.9.1. Users should upgrade to the latest version immediately. Additionally, the project maintainers note that inline JavaScript is not recommended because it makes deploying a secure Content Security Policy (CSP) difficult [2][4].

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
django-js-reversePyPI
< 0.9.10.9.1

Affected products

2

Patches

2
a3b57d1e4424

Merge pull request #81 from ierror/fix-xss-when-using-js-reverse-inline

https://github.com/ierror/django-js-reverseThomas GraingerMay 9, 2019via ghsa
5 files changed · +28 2
  • django_js_reverse/core.py+12 1 modified
    @@ -8,6 +8,7 @@
     from django.conf import settings
     from django.core.exceptions import ImproperlyConfigured
     from django.template import loader
    +from django.utils.safestring import mark_safe
     from django.utils.encoding import force_text
     
     from . import rjsmin
    @@ -120,6 +121,16 @@ def generate_json(default_urlresolver, script_prefix=None):
         }
     
     
    +def _safe_json(obj):
    +    return mark_safe(
    +        json
    +        .dumps(obj)
    +        .replace('>', '\\u003E')
    +        .replace('<', '\\u003C')
    +        .replace('&', '\\u0026')
    +    )
    +
    +
     def generate_js(default_urlresolver):
         js_var_name = getattr(settings, 'JS_REVERSE_JS_VAR_NAME', JS_VAR_NAME)
         if not JS_IDENTIFIER_RE.match(js_var_name.upper()):
    @@ -147,7 +158,7 @@ def generate_js(default_urlresolver):
     
         data = generate_json(default_urlresolver, script_prefix)
         js_content = loader.render_to_string('django_js_reverse/urls_js.tpl', {
    -        'data': json.dumps(data),
    +        'data': _safe_json(data),
             'js_name': '.'.join([js_global_object_name, js_var_name]),
         })
     
    
  • django_js_reverse/templates/django_js_reverse/urls_js.tpl+1 1 modified
    @@ -1,6 +1,6 @@
     {{ js_name }} = (function () {
         "use strict";
    -    var data = {{ data|safe }};
    +    var data = {{ data }};
         function factory(d) {
             var url_patterns = d.urls;
             var url_prefix = d.prefix;
    
  • django_js_reverse/tests/test_urls.py+1 0 modified
    @@ -20,6 +20,7 @@
     
         # test urls
         url(r'^test_no_url_args/$', dummy_view, name='test_no_url_args'),
    +    url(r'^test_script/$', dummy_view, name='</script><script>console.log(&amp;)</script><!--'),
         url(r'^test_one_url_args/(?P<arg_one>[-\w]+)/$', dummy_view, name='test_one_url_args'),
         url(r'^test_two_url_args/(?P<arg_one>[-\w]+)-(?P<arg_two>[-\w]+)/$', dummy_view, name='test_two_url_args'),
         url(r'^test_optional_url_arg/(?:1_(?P<arg_one>[-\w]+)-)?2_(?P<arg_two>[-\w]+)/$', dummy_view,
    
  • django_js_reverse/tests/unit_tests.py+10 0 modified
    @@ -265,6 +265,7 @@ def test_script_prefix(self):
     
     @override_settings(
         ROOT_URLCONF='django_js_reverse.tests.test_urls',
    +
         TEMPLATE_CONTEXT_PROCESSORS=['django.core.context_processors.request'],
     )
     class JSReverseTemplateTagTest(AbstractJSReverseTestCase, TestCase):
    @@ -288,6 +289,15 @@ def test_tpl_tag_without_request_in_context(self):
             js_from_view = smart_str(self.client.post('/jsreverse/').content)
             self.assertEqual(js_from_tag, js_from_view)
     
    +    def test_tpl_tag_escape_entities(self):
    +        context_instance = Context()
    +        tpl = Template('{% load js_reverse %}{% js_reverse_inline %}')
    +        js = tpl.render(context_instance)
    +        self.assertIn(
    +            '\\u003C/script\\u003E\\u003Cscript\\u003Econsole.log(\\u0026amp;)'
    +            '\\u003C/script\\u003E\\u003C!--',
    +            js,
    +        )
     
     if __name__ == '__main__':
         unittest.main()
    
  • README.rst+4 0 modified
    @@ -184,6 +184,10 @@ or, if you are using Django > 1.5
     Usage as template tag
     _____________________
     
    +You can place the js_reverse JavaScript inline into your templates,
    +however use of inline JavaScript is not recommended, because it
    +will make it impossible to deploy a secure Content Security Policy.
    +See `django-csp <https://django-csp.readthedocs.io/>`__
     
     ::
     
    
78d6aff2276f

avoid xss when using js_reverse_inline

https://github.com/ierror/django-js-reverseThomas GraingerMay 7, 2019via ghsa
5 files changed · +28 2
  • django_js_reverse/core.py+12 1 modified
    @@ -8,6 +8,7 @@
     from django.conf import settings
     from django.core.exceptions import ImproperlyConfigured
     from django.template import loader
    +from django.utils.safestring import mark_safe
     from django.utils.encoding import force_text
     
     from . import rjsmin
    @@ -120,6 +121,16 @@ def generate_json(default_urlresolver, script_prefix=None):
         }
     
     
    +def _safe_json(obj):
    +    return mark_safe(
    +        json
    +        .dumps(obj)
    +        .replace('>', '\\u003E')
    +        .replace('<', '\\u003C')
    +        .replace('&', '\\u0026')
    +    )
    +
    +
     def generate_js(default_urlresolver):
         js_var_name = getattr(settings, 'JS_REVERSE_JS_VAR_NAME', JS_VAR_NAME)
         if not JS_IDENTIFIER_RE.match(js_var_name.upper()):
    @@ -147,7 +158,7 @@ def generate_js(default_urlresolver):
     
         data = generate_json(default_urlresolver, script_prefix)
         js_content = loader.render_to_string('django_js_reverse/urls_js.tpl', {
    -        'data': json.dumps(data),
    +        'data': _safe_json(data),
             'js_name': '.'.join([js_global_object_name, js_var_name]),
         })
     
    
  • django_js_reverse/templates/django_js_reverse/urls_js.tpl+1 1 modified
    @@ -1,6 +1,6 @@
     {{ js_name }} = (function () {
         "use strict";
    -    var data = {{ data|safe }};
    +    var data = {{ data }};
         function factory(d) {
             var url_patterns = d.urls;
             var url_prefix = d.prefix;
    
  • django_js_reverse/tests/test_urls.py+1 0 modified
    @@ -20,6 +20,7 @@
     
         # test urls
         url(r'^test_no_url_args/$', dummy_view, name='test_no_url_args'),
    +    url(r'^test_script/$', dummy_view, name='</script><script>console.log(&amp;)</script><!--'),
         url(r'^test_one_url_args/(?P<arg_one>[-\w]+)/$', dummy_view, name='test_one_url_args'),
         url(r'^test_two_url_args/(?P<arg_one>[-\w]+)-(?P<arg_two>[-\w]+)/$', dummy_view, name='test_two_url_args'),
         url(r'^test_optional_url_arg/(?:1_(?P<arg_one>[-\w]+)-)?2_(?P<arg_two>[-\w]+)/$', dummy_view,
    
  • django_js_reverse/tests/unit_tests.py+10 0 modified
    @@ -265,6 +265,7 @@ def test_script_prefix(self):
     
     @override_settings(
         ROOT_URLCONF='django_js_reverse.tests.test_urls',
    +
         TEMPLATE_CONTEXT_PROCESSORS=['django.core.context_processors.request'],
     )
     class JSReverseTemplateTagTest(AbstractJSReverseTestCase, TestCase):
    @@ -288,6 +289,15 @@ def test_tpl_tag_without_request_in_context(self):
             js_from_view = smart_str(self.client.post('/jsreverse/').content)
             self.assertEqual(js_from_tag, js_from_view)
     
    +    def test_tpl_tag_escape_entities(self):
    +        context_instance = Context()
    +        tpl = Template('{% load js_reverse %}{% js_reverse_inline %}')
    +        js = tpl.render(context_instance)
    +        self.assertIn(
    +            '\\u003C/script\\u003E\\u003Cscript\\u003Econsole.log(\\u0026amp;)'
    +            '\\u003C/script\\u003E\\u003C!--',
    +            js,
    +        )
     
     if __name__ == '__main__':
         unittest.main()
    
  • README.rst+4 0 modified
    @@ -184,6 +184,10 @@ or, if you are using Django > 1.5
     Usage as template tag
     _____________________
     
    +You can place the js_reverse JavaScript inline into your templates,
    +however use of inline JavaScript is not recommended, because it
    +will make it impossible to deploy a secure Content Security Policy.
    +See `django-csp <https://django-csp.readthedocs.io/>`__
     
     ::
     
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.