Or simply use Django's builtin mechanism for that instead of poorly reimplementing it: <a href="https://docs.djangoproject.com/en/4.1/ref/templates/builtins/#json-script" rel="nofollow">https://docs.djangoproject.com/en/4.1/ref/templates/builtins...</a>
> <i>get_data_from_data_attribute({{ data|to_json }});</i><p>This constitutes an injection vulnerability that can be demonstrated with string "</script><script>alert(1<2)</script><script>".<p>If you want to inject arbitrary strings into a script tag, you need to reach for some more exotic escapes, starting with things like </script> → <\/script> or \u003c/script>. But I’m not going to give you a complete solution because I don’t want you to think this is a good idea. (But if you really want to know: look at the <i>script data state</i> in the HTML spec, and follow the parser. All up, you could do it two different ways, one requiring three things and the other two, though one of the two/three is impossible after JSON encoding.)<p>People often treat auto-escaping template languages as safe to do anything in, but they’re just <i>not</i> if you use HTML syntax—there are quite a few hazards to be aware of. Here you disabled auto-escaping (mark_safe in the to_json body) because the auto-escaping broke things in one way, but it introduced another vulnerability. For sanity in this context, you need to use XML syntax (by serving with the MIME type application/xhtml+xml), though some JavaScript libraries might misbehave due to side-effects if they make bad assumptions, and third-party templates might not be designed for XML syntax. (All up, I don’t generally recommend using XML syntax, though it’s a close thing.)<p>Fun fact: you <i>can</i> actually use entity encoding in JavaScript in the HTML syntax… by using the <i>SVG</i> script tag instead of the HTML one:<p><pre><code> <svg><script>alert(1&lt;2)</script></svg></code></pre>
Uhh, don't use the "safe" filter on user data that you're embedding in javascript, as that introduces arbitrary code injection attacks.<p>As for the default representation not being flat like the author needed, you can use the "values_list" method on your queryset.<p>I worry that articles like this lead to "the blind leading the blind". The arbitrary js injection attack enabled by their first example is concerning, and really should be accompanied by a big disclaimer saying "don't mess around with this filter unless you actually know what you're doing".
Neat.<p>I guess I'm a little surprised that the Django REST Framework isn't mentioned, since I thought that's the go-to for pretty much everyone for this task. Certainly this post's code is lighter weight if all you need to do is send some data out of Django.<p><a href="https://www.django-rest-framework.org/" rel="nofollow">https://www.django-rest-framework.org/</a>