0

Considering the following piece of code rendered via PHP:

<script type="application/javascript">
    const str = '<?= $str ?>';
</script>

How to prepare the $str so it can be rendered safely?

P.S. Safely is defined as "JavaScript gets the same Unicode contents as $str has in PHP".

Denis Kulagin
  • 8,472
  • 17
  • 60
  • 129
  • You mean characters like `✓` ? – Roko C. Buljan Jun 25 '20 at 19:52
  • 3
    `const str = =json_encode($str)?>;` => it will add double quotes around it, escape the ones that are in the string if there are some, encode unicode characters... everything you need _(edited: oops, forgot the `=` sign)_ – blex Jun 25 '20 at 19:55
  • 1
    You could output a `base_encode`-ed string, and in JavaScript turn the string from base encoded into normal string again. Make sure all this is safe. Are you using user provided data in the JavaScript? Could lead to scripting attacks. – Maarten Veerman Jun 25 '20 at 20:22
  • I could be way off, but just throwing it out there in case it's what you're looking for. Maybe you're looking for the word "sanitize"? – J.Ko Jun 25 '20 at 20:47
  • @MaartenVeerman Not exactly user-data, but still coming from a third-party source. – Denis Kulagin Jun 26 '20 at 08:27
  • @blex Surely should be converted to answer. Does it shield from all kinds of XSS attacks? – Denis Kulagin Jun 26 '20 at 08:30

1 Answers1

2

You could use PHP's json_encode:

<script type="application/javascript">
  const str = <?=json_encode($str)?>;
</script>

This will return a JSON representation of your String, meaning that:

  • it will be wrapped with double quotes
  • escape double quotes which might be in the String itself
  • escape Unicode characters

With this code alone (const str = ...), there is absolutely zero risk of XSS. The String is safe by itself, and can be manipulated by JS.

However, it can become an XSS hazard if you use that String like this:

  • eval(str); for obvious reasons
  • elem.innerHTML = str; for example if str === '<button onclick="sendCookiesToEvilServer()">Click me</button>', or '<style>body { display: none; }</style>'
  • ... that list is not exhaustive

If you want to display that String to the user, prefer .innerText to .innerHTML, or maybe look at strip_tags.

If you do need to use innerHTML because the string is allowed to contain some HTML, you need to properly sanitize it against XSS. And it's a little harder, because then, you need a parser to allow/remove only some HTML tags and/or attributes. strip_tags will allow you to do so to a certain extent (i.e. you could only allow <b> for example, but that won't prevent that <b> from having an attribute onclick="...").

blex
  • 24,941
  • 5
  • 39
  • 72