alt-rock
alt-rock

Reputation: 357

Properly escape javascript object

Given an object: {"key":"pairs","are":"fun"} that is echoed into a variable like const foo = <?php echo $bar ?>;. What is the proper way to escape the object? I've tried encode_json which escapes all the double quotes {\"key\":\"pairs\",\"are\":\"fun\"} disallowing the object to render. I have also tried esc_js which converts the double quotes to & quot;. How do i properly escape the object and return the object to foo? The out should be {"key":"pairs","are":"fun"} escaped of any malicious content.

Upvotes: 0

Views: 1583

Answers (1)

EPB
EPB

Reputation: 4029

If you use wp_json_encode to produce the JSON string itself, the output where you assign the JSON to a JavaScript variable in the browser should be reasonably safe. The wp_json_encode function will escape the characters that might otherwise allow someone to inject code at the point of assignment.

However, you also have to consider how your values in the key/value pairs will be used. If you're expecting an integer, maybe run the value through intval or if you are expecting plaintext that you're injecting into the page later, perhaps run it through esc_html.

For example:

<?php
$map = [
        'key' => 'pairs',
        'are' => '"; I document.write(\'fun trying to break out\')',
        'i_am_expecting_plaintext' => esc_html('<a href="evillinkhere">Hello</a><script>evilscript();</script>'),
        'i_expect_an_integer' => intval("90i"), 
        'some_html_allowed' => wp_kses('<a href="http://nisamerica.com/">here</a><script>dangerous();</script>', ['a' => array('href'=>array())]),
];
?>

<script>const foo = <?php echo wp_json_encode($map, JSON_PRETTY_PRINT); ?>;</script>

Produces the following output:

<script>const foo = {
    "key": "pairs",
    "are": "\"; I document.write('fun trying to break out')",
    "i_am_expecting_plaintext": "&lt;a href=&quot;evillinkhere&quot;&gt;Hello&lt;\/a&gt;&lt;script&gt;evilscript();&lt;\/script&gt;",
    "i_expect_an_integer": 90,
    "some_html_allowed": "<a href=\"http:\/\/nisamerica.com\/\">here<\/a>dangerous();"
};</script>

Addendum:

The reason wp_json_encode was giving you {\"key\":\"pairs\",\"are\":\"fun\"} before is that you were providing it a string that was already in JSON-notation. What wp_json_encode does is take native PHP variables and escape them as JSON. It's a pretty thin wrapper around json_encode really. My suggestion above is really to just produce the map in PHP, and feed that to the encode function instead of making your string representation and then trying to make it safe.

Upvotes: 1

Related Questions