trust(html)
Description
Convertit une chaîne de caractères HTML ou SVG en HTML ou SVG non échappé. N'utilisez m.trust
qu'avec des entrées utilisateur nettoyées.
Essayez toujours d'utiliser une autre méthode avant d'envisager d'utiliser m.trust
.
Signature
vnode = m.trust(html)
Argument | Type | Required | Description |
---|---|---|---|
html | String | Yes | Une chaîne de caractères contenant du code HTML ou SVG |
returns | Vnode | Un vnode HTML de confiance représentant la chaîne d'entrée |
Comment ça marche
Par défaut, Mithril.js protège toutes les valeurs afin d'éviter une catégorie de problèmes de sécurité appelés injections 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>
Cependant, il est parfois souhaitable d'afficher du texte enrichi et du balisage de formatage. Pour répondre à ce besoin, m.trust
crée des vnodes HTML de confiance qui sont rendus en tant que 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>
Les vnodes HTML de confiance sont des objets, pas des chaînes de caractères ; ils ne peuvent donc pas être concaténés avec des chaînes de caractères ordinaires.
Considérations de sécurité
Vous devez impérativement nettoyer les entrées de m.trust
afin de vous assurer de l'absence de code malveillant généré par l'utilisateur dans la chaîne HTML. Si vous ne nettoyez pas une chaîne HTML et que vous la marquez comme chaîne de confiance, tout code JavaScript asynchrone contenu dans cette chaîne HTML sera déclenché et exécuté avec le niveau d'autorisation de l'utilisateur consultant la page.
Il existe de nombreuses façons pour une chaîne HTML de contenir du code exécutable. Les moyens les plus courants d'injecter des attaques de sécurité consistent à ajouter des attributs onload
ou onerror
aux balises <img>
ou <iframe>
. L'utilisation de guillemets déséquilibrés tels que " onerror="alert(1)
permet également d'injecter des contextes exécutables dans des interpolations de chaînes non sécurisées.
var data = {};
// Sample vulnerable HTML string
var description =
"<img alt='" + data.title + "'> <span>" + data.description + '</span>';
// An attack using JavaScript-related attributes
data.description = "<img onload='alert(1)'>";
// An attack using unbalanced tags
data.description = "</span><img onload='alert(1)'><span";
// An attack using unbalanced quotes
data.title = "' onerror='alert(1)";
// An attack using a different attribute
data.title = "' onmouseover='alert(1)";
// An attack that does not use JavaScript
data.description =
"<a href='https://evil.com/login-page-that-steals-passwords.html'>Click here to read more</a>";
Il existe d'innombrables façons non évidentes de créer du code malveillant. Il est donc fortement recommandé d'utiliser une liste blanche des balises HTML, des attributs et des valeurs d'attribut autorisés, plutôt qu'une liste noire pour nettoyer les entrées utilisateur. Il est également fortement recommandé d'utiliser un analyseur HTML approprié, au lieu d'expressions régulières pour le nettoyage, car les expressions régulières sont extrêmement difficiles à tester pour tous les cas limites.
Scripts qui ne s'exécutent pas
Bien qu'il existe de nombreuses manières détournées de permettre à une chaîne HTML d'exécuter du JavaScript, les balises <script>
ne s'exécutent pas lorsqu'elles sont présentes dans une chaîne HTML.
Pour des raisons historiques, les navigateurs ignorent les balises <script>
qui sont insérées dans le DOM via innerHTML
. Ils agissent ainsi car une fois l'élément prêt (et donc, a une propriété innerHTML
accessible), les moteurs de rendu ne peuvent pas revenir en arrière à l'étape d'analyse si le script appelle quelque chose comme document.write("</body>")
.
Ce comportement du navigateur peut sembler surprenant pour un développeur venant de jQuery, car jQuery implémente du code spécifiquement pour trouver les balises de script et les exécuter dans ce scénario. Mithril.js suit le comportement du navigateur. Si le comportement de jQuery est souhaité, vous devriez envisager soit de déplacer le code hors de la chaîne HTML et dans une méthode de cycle de vie oncreate
, soit d'utiliser jQuery (ou de réimplémenter son code d'analyse de script).
Éviter de faire confiance au HTML
En général, il est préférable d'éviter d'utiliser m.trust
, sauf si vous devez absolument afficher du texte enrichi et qu'aucune autre solution ne permet d'obtenir le résultat souhaité.
// AVOID
m('div', m.trust('hello world'));
// PREFER
m('div', 'hello world');
Éviter de copier-coller aveuglément
L'utilisation de m.trust
lors de la manipulation de services tiers dont les tutoriels incluent du code HTML à copier-coller est une erreur fréquente. Dans la plupart des cas, le HTML doit être écrit à l'aide de vnodes (généralement via l'utilitaire m()
).
Voici l'exemple d'extrait de code pour le bouton J'aime 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>
Et voici comment le refactoriser en un composant Mithril.js d'une manière qui évite 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]'
),
];
},
};
Le composant Mithril.js ci-dessus copie simplement le code de la balise de script dans le hook oncreate
et déclare les balises HTML restantes en utilisant la syntaxe m()
de Mithril.js.
Éviter les entités HTML
L'utilisation de m.trust
pour les entités HTML est une erreur fréquente. Une meilleure approche consiste à utiliser les caractères Unicode correspondants :
// AVOID
m('h1', 'Coca-Cola', m.trust('™'));
// PREFER
m('h1', 'Coca-Cola™');
Les caractères Unicode pour les caractères accentués peuvent être saisis à l'aide d'une disposition de clavier adaptée à la langue, et il est également possible de mémoriser les raccourcis clavier pour produire des symboles couramment utilisés (par exemple, Alt+0153
sous Windows, ou Option+2
sur Mac pour le symbole ™). Une autre méthode simple consiste à copier-coller le caractère souhaité depuis une table de caractères unicode. Une autre méthode consiste à saisir un point de code Unicode échappé (par exemple, "\u2122"
pour le symbole ™).
Tous les caractères représentables sous forme d'entités HTML possèdent un équivalent Unicode, y compris les caractères invisibles tels que
et ­
.
Pour éviter les problèmes d'encodage, il est nécessaire de définir l'encodage du fichier sur UTF-8 dans le fichier JavaScript et d'ajouter la balise <meta charset="utf-8">
dans le fichier HTML hôte.