trust(html)
Descrizione
Trasforma una stringa HTML o SVG in HTML o SVG senza eseguire l'escape dei caratteri. Non utilizzare m.trust
con input utente non sanificati.
Si raccomanda di valutare un metodo alternativo prima di ricorrere a m.trust
.
Firma
vnode = m.trust(html)
Argomento | Tipo | Richiesto | Descrizione |
---|---|---|---|
html | String | Sì | Una stringa HTML o SVG. |
restituisce | Vnode | Un vnode di tipo HTML vnode che rappresenta la stringa di input, contrassegnato come attendibile. |
Come funziona
Per impostazione predefinita, Mithril.js esegue l'escape di tutti i valori per prevenire problemi di sicurezza noti come attacchi XSS (Cross-site scripting).
var userContent = "<script>alert('evil')</script>";
var view = m('div', userContent);
m.render(document.body, view);
// HTML equivalente
// <div><script>alert('evil')</script></div>
Tuttavia, in alcuni casi è necessario renderizzare testo formattato e markup. Per questo scopo, m.trust
crea vnode HTML vnode contrassegnati come attendibili, che vengono renderizzati come HTML.
var view = m('div', [m.trust("<h1>Here's some <em>HTML</em></h1>")]);
m.render(document.body, view);
// HTML equivalente
// <div><h1>Here's some <em>HTML</em></h1></div>
I vnode HTML attendibili sono oggetti, non stringhe; pertanto, non possono essere concatenati con stringhe normali.
Considerazioni sulla sicurezza
È fondamentale sanificare l'input di m.trust
per garantire che la stringa HTML non contenga codice dannoso proveniente dall'utente. Se una stringa HTML non viene sanificata e viene contrassegnata come attendibile, qualsiasi codice JavaScript asincrono in essa contenuto verrà attivato ed eseguito con i permessi dell'utente che visualizza la pagina.
Gli attacchi di sicurezza vengono comunemente iniettati aggiungendo attributi onload
o onerror
ai tag <img>
o <iframe>
, oppure usando virgolette non chiuse come " onerror="alert(1)
per iniettare contesti eseguibili in stringhe interpolate non sanificate.
var data = {};
// Esempio di stringa HTML vulnerabile
var description =
"<img alt='" + data.title + "'> <span>" + data.description + '</span>';
// Attacco che sfrutta attributi JavaScript
data.description = "<img onload='alert(1)'>";
// Attacco che utilizza tag non bilanciati
data.description = "</span><img onload='alert(1)'><span";
// Attacco che utilizza virgolette non bilanciate
data.title = "' onerror='alert(1)";
// Attacco che utilizza un attributo diverso
data.title = "' onmouseover='alert(1)";
// Attacco che non fa uso di JavaScript
data.description =
"<a href='https://evil.com/login-page-that-steals-passwords.html'>Clicca qui per saperne di più</a>";
Data l'infinita varietà di metodi, anche non evidenti, per creare codice dannoso, si raccomanda vivamente di utilizzare una whitelist (lista consentiti) di tag HTML, attributi e valori di attributi consentiti, piuttosto che una blacklist (lista bloccati) per sanificare l'input dell'utente. È inoltre altamente raccomandato utilizzare un parser HTML appropriato, invece di espressioni regolari per la sanificazione, perché le espressioni regolari sono estremamente difficili da testare per tutti i casi limite.
Script che non vengono eseguiti
Anche se ci sono molti modi oscuri per far eseguire JavaScript a una stringa HTML, i tag <script>
non vengono eseguiti quando appaiono in una stringa HTML.
Per motivi storici, i browser ignorano i tag <script>
inseriti nel DOM tramite innerHTML
. Questo perché, una volta che l'elemento è pronto (e quindi la sua proprietà innerHTML
è accessibile), i motori di rendering non possono tornare alla fase di parsing se lo script invoca un comando come document.write("</body>")
.
Questo comportamento del browser può sembrare sorprendente a uno sviluppatore abituato a jQuery, perché jQuery implementa codice specifico per trovare i tag script ed eseguirli in questo scenario. Mithril.js segue il comportamento del browser. Se si desidera il comportamento di jQuery, si consiglia di spostare il codice dalla stringa HTML e in un metodo del ciclo di vita oncreate
, oppure utilizzare jQuery (o re-implementare il suo codice di parsing degli script).
Evitare di fidarsi dell'HTML
In generale, è consigliabile evitare l'uso di m.trust
a meno che non sia strettamente necessario renderizzare testo formattato e non esistano alternative per ottenere il risultato desiderato.
// EVITARE
m('div', m.trust('hello world'));
// PREFERIRE
m('div', 'hello world');
Evitare di copiare e incollare alla cieca
Un errore comune nell'uso di m.trust
si verifica quando si lavora con servizi di terze parti i cui tutorial includono codice HTML da copiare e incollare. Nella maggior parte dei casi, l'HTML dovrebbe essere scritto usando i vnode (tipicamente tramite l'utility m()
).
Ecco l'esempio di snippet per il pulsante Mi piace di Facebook:
<!-- Carica l'SDK di Facebook per 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>
<!-- Il tuo codice del pulsante Mi piace -->
<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>
Ed ecco come rifattorizzare in un componente Mithril.js evitando 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]'
),
];
},
};
Il componente Mithril.js precedente si limita a copiare il codice dello script nell'hook oncreate
e dichiara i restanti tag HTML utilizzando la sintassi m()
di Mithril.js.
Evitare le entità HTML
Un uso improprio comune di m.trust
è l'utilizzo per le entità HTML. Un approccio migliore è utilizzare i corrispondenti caratteri Unicode:
// EVITARE
m('h1', 'Coca-Cola', m.trust('™'));
// PREFERIRE
m('h1', 'Coca-Cola™');
I caratteri Unicode per le lettere accentate possono essere inseriti tramite un layout di tastiera specifico per la lingua desiderata; in alternativa, si possono memorizzare le scorciatoie da tastiera per i simboli più comuni (ad esempio, Alt+0153
su Windows o Option+2
su Mac per il simbolo ™). Un altro modo semplice per ottenerli è semplicemente copiare e incollare il carattere desiderato da una tabella dei caratteri unicode. Un approccio alternativo consiste nel digitare il codepoint Unicode in forma escaped (ad esempio, "\u2122"
per il simbolo ™).
Tutti i caratteri che sono rappresentabili come entità HTML hanno equivalenti Unicode, inclusi i caratteri non visibili come
e ­
.
Per evitare problemi di codifica, è necessario impostare la codifica del file su UTF-8 nel file JavaScript, nonché aggiungere il meta tag <meta charset="utf-8">
nel file HTML principale.