trust(html)
Descrição
Converte uma string HTML ou SVG em HTML ou SVG não escapado. Não use m.trust
com dados de entrada do usuário que não foram validados.
Sempre tente usar um método alternativo antes de considerar usar m.trust
.
Assinatura
vnode = m.trust(html)
Argumento | Tipo | Obrigatório | Descrição |
---|---|---|---|
html | String | Sim | Uma string contendo texto HTML ou SVG. |
retorno | Vnode | Um vnode HTML confiável que representa a string de entrada. |
Como funciona
Por padrão, o Mithril.js escapa todos os valores para evitar uma classe de problemas de segurança chamada injeções 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>
No entanto, às vezes é desejável renderizar texto rico e marcação de formatação. Para atender a essa necessidade, m.trust
cria vnodes HTML confiáveis que são renderizados 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>
Vnodes HTML confiáveis são objetos, não strings; portanto, eles não podem ser concatenados com strings regulares.
Considerações de segurança
Você deve validar a entrada de m.trust
para garantir que não haja código malicioso gerado pelo usuário na string HTML. Se você não validar uma string HTML e marcá-la como confiável, qualquer código JavaScript assíncrono dentro da string HTML será acionado e executado com o nível de permissão do usuário que está visualizando a página.
Existem diversas maneiras pelas quais uma string HTML pode conter código executável. As maneiras mais comuns de injetar ataques de segurança são adicionar atributos onload
ou onerror
em tags <img>
ou <iframe>
, e usar aspas desbalanceadas, como " onerror="alert(1)
, para injetar contextos executáveis em interpolações de string não validadas.
var data = {};
// Exemplo de string HTML vulnerável
var description =
"<img alt='" + data.title + "'> <span>" + data.description + '</span>';
// Um ataque usando atributos relacionados ao JavaScript
data.description = "<img onload='alert(1)'>";
// Um ataque usando tags desbalanceadas
data.description = "</span><img onload='alert(1)'><span";
// Um ataque usando aspas desbalanceadas
data.title = "' onerror='alert(1)";
// Um ataque usando um atributo diferente
data.title = "' onmouseover='alert(1)";
// Um ataque que não usa JavaScript
data.description =
"<a href='https://evil.com/login-page-that-steals-passwords.html'>Click here to read more</a>";
Existem inúmeras maneiras não óbvias de criar código malicioso, por isso é altamente recomendável que você use uma whitelist de tags HTML, atributos e valores de atributos permitidos, em vez de uma blacklist para validar a entrada do usuário. Também é altamente recomendável que você use um parser HTML adequado, em vez de expressões regulares para validação, porque as expressões regulares são extremamente difíceis de testar para todos os casos extremos.
Scripts que não são executados
Ainda que existam muitas maneiras obscuras de fazer uma string HTML executar JavaScript, as tags <script>
não são executadas quando aparecem em uma string HTML.
Por razões históricas, os navegadores ignoram as tags <script>
que são inseridas no DOM via innerHTML
. Eles fazem isso porque, uma vez que o elemento está pronto (e, portanto, tem uma propriedade innerHTML
acessível), os mecanismos de renderização não podem voltar à fase de análise se o script chamar algo como document.write("</body>")
.
Este comportamento do navegador pode parecer surpreendente para um desenvolvedor vindo do jQuery, porque o jQuery implementa código especificamente para encontrar tags de script e executá-las neste cenário. O Mithril.js segue o comportamento do navegador. Se o comportamento do jQuery for desejado, você deve considerar mover o código para fora da string HTML e para um método de ciclo de vida oncreate
ou usar o jQuery (ou reimplementar seu código de análise de script).
Evite confiar em HTML
Como regra geral, você deve evitar o uso de m.trust
a menos que esteja renderizando explicitamente texto rico e não haja outra maneira de obter os resultados desejados.
// EVITE
m('div', m.trust('hello world'));
// PREFIRA
m('div', 'hello world');
Evite copiar e colar cegamente
Uma maneira comum de usar m.trust
de forma incorreta é ao trabalhar com serviços de terceiros cujos tutoriais incluem código HTML para ser copiado e colado. Na maioria dos casos, o HTML deve ser escrito usando vnodes (normalmente através do utilitário m()
).
Aqui está o snippet de exemplo para o botão Curtir do Facebook:
<!-- Carregue o SDK do Facebook para 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>
<!-- Seu código do botão Curtir -->
<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>
E aqui está como refatorar em um componente Mithril.js de uma forma 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]'
),
];
},
};
O componente Mithril.js acima simplesmente copia o código da tag de script para o hook oncreate
e declara as tags HTML restantes usando a sintaxe m()
do Mithril.js.
Evite entidades HTML
Uma maneira comum de usar m.trust
de forma incorreta é utilizá-lo para entidades HTML. Uma abordagem melhor é utilizar os caracteres Unicode correspondentes.
// EVITE
m('h1', 'Coca-Cola', m.trust('™'));
// PREFIRA
m('h1', 'Coca-Cola™');
Caracteres Unicode para caracteres acentuados podem ser digitados usando um layout de teclado para um idioma aplicável, e também pode-se optar por memorizar atalhos de teclado para produzir símbolos comumente usados (por exemplo, Alt+0153
no Windows ou Option+2
no Mac para o símbolo ™). Outro método simples para produzi-los é simplesmente copiar e colar o caractere desejado de uma tabela de caracteres Unicode. Outro método relacionado é digitar um code point Unicode escapado (por exemplo, "\u2122"
para o símbolo ™).
Todos os caracteres que são representáveis como entidades HTML têm contrapartidas Unicode, incluindo caracteres não visíveis como
e ­
.
Para evitar problemas de codificação, você deve definir a codificação do arquivo para UTF-8 no arquivo JavaScript, assim como adicionar a tag meta <meta charset="utf-8">
no arquivo HTML hospedeiro.