JSON_HEX_TAG
Si está haciendo eco en JS dentro de un documento HTML (como lo está en su ejemplo), es necesario o corre el riesgo de abrir una gran vulnerabilidad de XSS. Sin este, un atacante puede publicar algo como esto:
</script>alert("XSS");</script>
Desde PHP 5.4, esto se ha solucionado y las barras diagonales se escapan de forma predeterminada, pero aún así, nunca se sabe en qué versión de PHP se ejecutará su código. Mejor prevenir que lamentar.
Como señala OP, incluso en las versiones nunca de PHP puede insertar un <!--
para desordenar toda la página, lo que posiblemente cause un comportamiento inesperado. Así que la bandera es realmente necesaria en todas las versiones de PHP.
JSON_HEX_QUOT y JSON_HEX_APOS
Para entender lo que esto hace, eche un vistazo al siguiente ejemplo:
$array = array(
"a" => "'",
"b" => '"',
);
// This will output {"a":"'","b":"\""}
echo json_encode($array);
// This will output {"a":"\u0027","b":"\u0022"}
echo json_encode($array, JSON_HEX_QUOT | JSON_HEX_APOS);
Por lo tanto, las comillas alrededor de los literales de cadena nunca se codifican. Las citas dentro de los literales de cadena serán escapadas sin las banderas, y codificadas con ellas.
De acuerdo con sus referencias, esto se usa para hacer que la salida sea segura para usar dentro de los controladores de eventos (es decir, los atributos HTML). Es cierto que no son estrictamente necesarios dentro de las etiquetas de script, pero no es del todo correcto que estén a salvo en los controladores de eventos.
Eche un vistazo a este ejemplo, por ejemplo:
<?php $data = array(" onmouseenter=alert(1) " => "foo"); ?>
<a onclick="x = <?= json_encode($data, JSON_HEX_QUOT | JSON_HEX_APOS); ?>">test</a>
Resultando en:
<a onclick="x = {" onmouseenter=alert(1) ": "foo"}">test</a>
Creo que estás seguro si siempre encierras los valores de tus atributos entre comillas simples, pero aún así parece un poco arriesgado.
JSON_HEX_AMP
Cotizando su referencia aquí:
Para compatibilidad con bloques de script XHTML no CDATA, haga & también.
Entonces, como estás haciendo HTML5, esto no se aplica a ti, y no creo que haya una vulnerabilidad de seguridad aquí de todos modos. Sin embargo, no hace daño codificar.
Conclusión
- Para su uso, dentro de una etiqueta de script en HTML5, solo usar
JSON_HEX_TAG
es suficiente.
- Hacer esto dentro de los atributos (controladores de eventos) es peligroso, al menos a menos que esté entre comillas simples.
- Si fuera usted, crearía una pequeña función de ayuda llamada
safe_json_encode
que usa las cuatro marcas, y luego la usaría solo en las etiquetas de secuencia de comandos. Codificar más de lo necesario no te hace daño.
Notas adicionales
- Asegúrese de servir la página con un tipo de contenido y codificación de caracteres correctos. Desordenar esto puede llevar a maneras de evitar la codificación.
- Si luego envía los valores de las variables a HTML, debe pensar en XSS nuevamente. Usando los valores de su JSON en, por ejemplo.
innerHTML
o document.write
no serán seguros. (Veo que lidias con esto en tu segunda línea de guión).
Descargo de responsabilidad: />> Esto se basa en la investigación que realicé hoy. No soy un gurú de PHP. Si confías en esto para algo crítico, probablemente quieras investigar más por tu cuenta para asegurarte de que no me esté perdiendo algo aquí.