how do I esc them?
You don’t, both approaches are fundamentally wrong in multiple ways that make them irrecoverable.
First Case
echo "<script> alert( 'Authorization successful. Hello ' + '$me')</script>";
In this scenario we are trying to use alert
to display a string, and append both values together. Aside from the usage of alert
there are several mistakes:
- If we want to insert the PHP variable
$me
into the JS string, why are we doing the concatenation in javascript? - We don’t know what
$me
is or where it’s coming from
The final product of this should be an alert
function that takes a variable or a hardcoded string, no variations on that. So there will not be a +
operator.
Additionally, we do not know what’s considered acceptable here, escaping is all about context and enforcing expectations but none have been provided. e.g. are HTML tags acceptable? Do we only want numbers and letters? Is it an email? The answers to these questions determine how you would escape the value.
This is the closest to an answer as you asked for it, and it’s not reliably secure:
?>
<script>alert(<?php echo wp_json_encode( 'Authorization successful. Hello ' . $me ); ?> );</script>
<?php
Because we do not know $me
contains or what it’s intended to do, we have to assume you want to display a plaintext string safely with alert
. So we JSON encode it. If it’s a string it’ll be passed in as a string. Notice that the string concatenation is happening in PHP, not JS. If $me
is not a string then this code will fail.
Second Case
echo "<script> window.location.replace('$url'); </script>";
Here we can safely assume that $url
is meant to hold a URL, therefore esc_url
would be appropriate, but we can’t dump that into a JS snippet directly.
The next best thing we can try is this:
echo "<script> window.location.replace( ". wp_json_encode( esc_url( $url ) ) . " ); </script>";
Important
- Don’t just use
wp_json_encode
everywhere, it isn’t the magic fix all escaping function for JS. The true fix is to never need to insert PHP variables directly into printed JS. It’s a strong code smell and a strong indicator that you’ve done something terribly wrong.- e.g. how would this work:
alert( { object... } );
or<a href=""malicious string""
- if you know the type of the value you can be more specific, e.g.
intval
would be more appropriate for a number - WordPress already has a mechanism for exposing data to javascript, e.g.
wp_add_inline_script
, see https://developer.wordpress.org/reference/functions/wp_add_inline_script/ - In general you want to avoid printing a
<script>
tag with javascript inside from PHP, even if there are no variables, unless you really have to. Most of the times I’ve done it are for 3rd party integrations in a footer/header, never for the core logic of what I’m building.
- e.g. how would this work:
- The example involving
window.location
should never make it into production code. There are no situations where this wouldn’t be better served by a PHP call towp_redirect
instead - Escaping isn’t a magic function you apply to data to make it safe, it’s a cookie cutter that guarantees assumptions. Why trust that a variable contains a URL when you can guarantee it using
esc_url
? Then if it isn’t a URL it’ll be mangled into the shape of a URL and disarmed.