Tagged templates para prevenir XSS
Guille Paz
Los template literals o template strings fueron un antes y después a la hora de manejar strings en JavaScript.
En lo personal los uso mucho para crear "componentes de HTML" y poder reutilizar el markup cuando no uso frameworks o librerías.
Lo que no sabía es que se pueden crear tagged templates
: funciones que permiten parsear los template literals de forma custom:
function rocket(strings) {
return `🚀 ${strings}!`;
};
console.log( rocket`to the moon` );
// '🚀 to the moon!'
Parece que no suma mucho ya que podríamos ejecutar una función y listo rocket('to the moon')
. Pero, pero, pero... al ser un tagged template
tenemos mucho más poder y control.
Como mencionaba anteriormente, uso mucho template literals para manejar el markup HTML y acá es donde se pone interesante la cuestión.
Un gran problema de seguridad al manejar templates y datos dinámicos son las vulnerabilidades de XSS.
function unSafeWelcomeTemplate(username) {
return`<h1>Hola, ${username}!</h1>`
};
const xss = 'Guille <img src="x" onerror="alert(\'xss\')"> Paz';
document.body.insertAdjacentHTML('beforeend', unsafeWelcomeTemplate(xss));
Muchos frameworks y librerías lo resuelven de forma automática y por eso no nos preocupamos de resolverlo, pero en el caso de no usar ninguno podemos crear un tagged template
que nos ayude.
La función safe
recibe los strings
y los values
de sustitución (los datos dinámicos), por lo que podríamos sanitizar los datos para prevenir un XSS en nuestros templates.
import { escape } from "https://esm.sh/v90/[email protected]/es2022/html-escaper.js";
// safe: tagged template
function safe(strings, ...values) {
return String.raw({ raw: strings }, ...values.map(v => escape(v)));
};
function welcomeTemplate(username) {
return safe`<h1>Hola, ${username}!</h1>`
};
const xss = 'Guille <img src="x" onerror="alert(\'xss\')"> Paz';
document.body.insertAdjacentHTML('beforeend', welcomeTemplate(xss));
Uso la función estática String.raw
para poder iterar y formatear los valores sin perder el orden de las sustituciones.
Chao. 🚀