trust(html)
Descripción
Convierte una cadena HTML o SVG en código HTML/SVG sin escapar. No uses m.trust
con datos provenientes de entradas de usuario no sanitizadas.
Intenta siempre usar un método alternativo antes de considerar el uso de m.trust
.
Firma
vnode = m.trust(html)
Argumento | Tipo | Requerido | Descripción |
---|---|---|---|
html | String | Sí | Una cadena que contiene texto HTML o SVG. |
retorna | Vnode | Un vnode HTML confiable que representa la cadena de entrada. |
Cómo funciona
De forma predeterminada, Mithril.js escapa todos los valores para prevenir una clase de problemas de seguridad conocidos como inyecciones XSS.
var userContent = "<script>alert('evil')</script>";
var view = m('div', userContent);
m.render(document.body, view);
// equivalent HTML
// <div><script>alert('evil')</script></div>
Sin embargo, a veces es deseable renderizar texto enriquecido y marcado de formato. Para satisfacer esa necesidad, m.trust
crea vnodes HTML confiables que se renderizan como HTML.
var view = m('div', [m.trust("<h1>Here's some <em>HTML</em></h1>")]);
m.render(document.body, view);
// equivalent HTML
// <div><h1>Here's some <em>HTML</em></h1></div>
Los vnodes HTML de confianza son objetos, no cadenas; por lo tanto, no pueden concatenarse con cadenas normales.
Consideraciones de seguridad
Debes sanitizar la entrada de m.trust
para asegurarte de que no haya código malicioso generado por el usuario en la cadena HTML. Si no limpias una cadena HTML y la marcas como confiable, cualquier llamada asíncrona de JavaScript dentro de la cadena HTML se activará y se ejecutará con el nivel de autorización del usuario que está viendo la página.
Hay muchas maneras en las que una cadena HTML puede contener código ejecutable. Las formas más comunes de inyectar ataques de seguridad son agregar atributos onload
u onerror
en etiquetas <img>
o <iframe>
, y usar comillas desequilibradas como " onerror="alert(1)
para inyectar contextos ejecutables en interpolaciones de cadenas no limpias.
var data = {};
// Ejemplo de cadena HTML vulnerable
var description =
"<img alt='" + data.title + "'> <span>" + data.description + '</span>';
// Un ataque con atributos de JavaScript
data.description = "<img onload='alert(1)'>";
// Un ataque usando etiquetas no balanceadas
data.description = "</span><img onload='alert(1)'><span";
// Un ataque usando comillas no balanceadas
data.title = "' onerror='alert(1)";
// Un ataque con un atributo diferente
data.title = "' onmouseover='alert(1)";
// Un ataque sin JavaScript
data.description =
"<a href='https://evil.com/login-page-that-steals-passwords.html'>Click here to read more</a>";
Existen innumerables formas no evidentes de crear código malicioso, por lo que se recomienda usar una lista blanca de etiquetas HTML, atributos y valores de atributos permitidos, en lugar de una lista negra para limpiar la entrada del usuario. También se recomienda usar un analizador HTML adecuado, en lugar de expresiones regulares para la limpieza, porque las expresiones regulares son extremadamente difíciles de probar para todos los casos límite.
Scripts que no se ejecutan
Aunque hay muchas formas oscuras de hacer que una cadena HTML ejecute JavaScript, las etiquetas <script>
no se ejecutan cuando aparecen en una cadena HTML.
Por razones históricas, los navegadores ignoran las etiquetas <script>
que se insertan en el DOM a través de innerHTML
. Hacen esto porque una vez que el elemento está listo (y, por lo tanto, tiene una propiedad innerHTML
accesible), los motores de renderizado no pueden volver a la fase de análisis si el script llama a algo como document.write("</body>")
.
Este comportamiento del navegador puede parecer sorprendente para un desarrollador que viene de jQuery, porque jQuery implementa código específicamente para encontrar etiquetas de script y ejecutarlas en este escenario. Mithril.js sigue el comportamiento del navegador. Si se desea el comportamiento de jQuery, debes mover el código fuera de la cadena HTML y dentro de un método de ciclo de vida oncreate
, o usar jQuery (o reimplementar su código de análisis de script).
Evita confiar en HTML
Como regla general, debes evitar usar m.trust
a menos que estés renderizando explícitamente texto enriquecido y no haya otra forma de obtener los resultados que buscas.
// EVITAR
m('div', m.trust('hello world'));
// PREFERIR
m('div', 'hello world');
Evita copiar y pegar a ciegas
Una forma común de usar m.trust
de forma incorrecta es cuando se trabaja con servicios de terceros cuyos tutoriales incluyen código HTML para copiar y pegar. En la mayoría de los casos, el HTML debe escribirse usando vnodes (típicamente a través de la utilidad m()
).
Aquí está el fragmento de ejemplo para el botón Me gusta de Facebook:
<!-- Load Facebook SDK for JavaScript -->
<div id="fb-root"></div>
<script>
(function (d, s, id) {
var js,
fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = '//connect.facebook.net/en_US/sdk.js#xfbml=1';
fjs.parentNode.insertBefore(js, fjs);
})(document, 'script', 'facebook-jssdk');
</script>
<!-- Your like button code -->
<div
class="fb-like"
data-href="https://www.your-domain.com/your-page.html"
data-layout="standard"
data-action="like"
data-show-faces="true"
></div>
Y aquí está cómo refactorizar en un componente de Mithril.js de una manera que evite m.trust
:
var FacebookLikeButton = {
oncreate: function () {
(function (d, s, id) {
var js,
fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = '//connect.facebook.net/en_US/sdk.js#xfbml=1';
fjs.parentNode.insertBefore(js, fjs);
})(document, 'script', 'facebook-jssdk');
},
view: function () {
return [
m('#fb-root'),
m(
'.fb-like[data-href=https://www.your-domain.com/your-page.html][data-layout=standard][data-action=like][data-show-faces=true]'
),
];
},
};
El componente de Mithril.js anterior simplemente copia el código de la etiqueta de script en el hook oncreate
y declara las etiquetas HTML restantes usando la sintaxis m()
de Mithril.js.
Evita las entidades HTML
Una mejor opción es usar los caracteres Unicode correspondientes.
// EVITAR
m('h1', 'Coca-Cola', m.trust('™'));
// PREFERIR
m('h1', 'Coca-Cola™');
Los caracteres Unicode para caracteres acentuados se pueden escribir usando una distribución de teclado para un idioma aplicable, y también se puede optar por memorizar atajos de teclado para producir símbolos de uso común (por ejemplo, Alt+0153
en Windows, u Option+2
en Mac para el símbolo ™). Otro método simple para producirlos es simplemente copiar y pegar el carácter deseado de una tabla de caracteres unicode. Otro método relacionado es escribir un punto de código unicode con escape (por ejemplo, "\u2122"
para el símbolo ™).
Todos los caracteres que son representables como entidades HTML tienen contrapartes unicode, incluidos los caracteres no visibles como
y ­
.
Para evitar problemas de codificación, debes configurar la codificación del archivo JavaScript a UTF-8, así como agregar la metaetiqueta <meta charset="utf-8">
en el archivo HTML principal.