Le système d'extensions de Chrome applique une Content Security Policy (CSP) par défaut assez stricte.
Les restrictions imposées par nos règles sont simples: le script doit être déplacé hors ligne dans
les fichiers JavaScript, les gestionnaires d'événements intégrés doivent être convertis pour utiliser addEventListener
, et eval()
est
est désactivé. Les applications Chrome ont des règles encore plus strictes, et nous sommes très satisfaits de la sécurité.
de ces règles.
Nous reconnaissons cependant que diverses bibliothèques utilisent des constructions de type eval()
et eval
, telles que
new Function()
pour optimiser les performances et faciliter l'expression. Les bibliothèques de modèles
particulièrement sujette
à ce style d’implémentation. Certains (comme Angular.js) sont compatibles avec CSP.
standard, de nombreux frameworks populaires n'ont pas encore adopté de mécanisme compatible avec
"Extensions" dans un monde sans eval
. La suppression de la prise en charge de cette fonctionnalité s'est donc avérée plus
que prévu pour les développeurs.
Ce document présente le bac à sable, un mécanisme sécurisé pour inclure ces bibliothèques dans vos projets. sans compromettre la sécurité. Par souci de concision, nous utiliserons le terme extensions tout au long de la présentation, mais le concept s'applique également aux applications.
Pourquoi utiliser le bac à sable ?
eval
est dangereux dans une extension, car le code qu'elle exécute a accès à tout ce qui se trouve dans le
l'environnement à autorisations élevées de l'extension. De nombreuses API chrome.*
performantes sont disponibles et pourraient
avoir de graves conséquences sur la sécurité et la vie privée de l'utilisateur ; l'exfiltration de données
simple est le cadet de nos soucis.
La solution proposée est un bac à sable dans lequel eval
peut exécuter du code sans accéder au
ou ses API à forte valeur ajoutée. Pas de données, pas d'API, pas de problème.
Pour ce faire, nous classons certains fichiers HTML dans le package d'extension comme étant "bac à sable".
Chaque fois qu'une page en bac à sable est chargée, elle est déplacée vers une origine unique et sa diffusion est refusée.
Accès aux API chrome.*
. Si nous chargeons cette page en bac à sable dans notre extension via un iframe
, nous pouvons
transmettre des messages, le laisser agir en fonction de ces messages et attendre qu'il nous renvoie
résultat. Ce mécanisme de messagerie simple nous donne tout ce dont nous avons besoin pour inclure de façon sécurisée des eval
dans le workflow de l'extension.
Créer et utiliser un bac à sable
Si vous souhaitez vous plonger directement dans le code, utilisez l'exemple d'extension de bac à sable et prenez désactivée. Il s'agit d'un exemple fonctionnel d'une petite API de messagerie basée sur le Handlebars. de création de modèles. Vous devriez obtenir tout ce dont vous avez besoin pour démarrer. Pour ceux d’entre vous qui un peu plus d'explications, examinons ensemble cet exemple ici.
Lister les fichiers dans le fichier manifeste
Chaque fichier devant être exécuté dans un bac à sable doit être répertorié dans le fichier manifeste de l'extension en ajoutant un
sandbox
. Il s'agit d'une étape critique et facile à oublier. Veuillez donc vérifier que
votre fichier en bac à sable est listé dans le fichier manifeste. Dans cet exemple, nous exécutons un bac à sable intelligent
nommé "sandbox.html". L'entrée du fichier manifeste se présente comme suit:
{
...,
"sandbox": {
"pages": ["sandbox.html"]
},
...
}
Charger le fichier en bac à sable
Pour effectuer une action intéressante avec le fichier en bac à sable, nous devons le charger dans un contexte où
il peut être traité par le code de l'extension. Ici, sandbox.html a été chargé dans la
Page d'événement (eventpage.html) de l'extension via iframe
. eventpage.js contient du code.
qui envoie un message dans le bac à sable à chaque clic sur l'action du navigateur en recherchant iframe
sur la page et exécuter la méthode postMessage
sur son contentWindow
. Le message est un objet
contenant deux propriétés: context
et command
. Nous aborderons les deux
dans un instant.
chrome.browserAction.onClicked.addListener(function() {
var iframe = document.getElementById('theFrame');
var message = {
command: 'render',
context: {thing: 'world'}
};
iframe.contentWindow.postMessage(message, '*');
});
postMessage
, consultez la documentation postMessage
sur MDN . C'est assez complet et il vaut la peine d'être lu. Notez en particulier que les données ne peuvent être transmises dans les deux sens que si elles sont sérialisables. Les fonctions, par exemple, ne le sont pas.Faire quelque chose de dangereux
Lors du chargement de sandbox.html
, il charge la bibliothèque Handlebars, puis crée et compile une ligne
de la même manière que Handlebars suggère:
<script src="handlebars-1.0.0.beta.6.js"></script>
<script id="hello-world-template" type="text/x-handlebars-template">
<div class="entry">
<h1>Hello, !</h1>
</div>
</script>
<script>
var templates = [];
var source = document.getElementById('hello-world-template').innerHTML;
templates['hello'] = Handlebars.compile(source);
</script>
Cela n'est pas une fatalité ! Même si Handlebars.compile
finit par utiliser new Function
, tout fonctionne
exactement comme prévu, et nous obtenons un modèle compilé dans templates['hello']
.
Transmettre le résultat
Nous allons mettre ce modèle à disposition en configurant un écouteur de messages qui accepte les commandes
sur la page "Événement". Nous utilisons le command
transmis pour déterminer ce qu'il faut faire (vous pouvez
ne vous contentez pas d'afficher peut-être pour créer des modèles ? Peut-être que vous les gérerez
méthode ?), et l'élément context
est transmis directement au modèle pour l'affichage. Code HTML affiché
sera renvoyé à la page d'événement afin que l'extension puisse s'en servir ultérieurement:
<script>
window.addEventListener('message', function(event) {
var command = event.data.command;
var name = event.data.name || 'hello';
switch(command) {
case 'render':
event.source.postMessage({
name: name,
html: templates[name](event.data.context)
}, event.origin);
break;
// case 'somethingElse':
// ...
}
});
</script>
De retour sur la page des événements, nous allons recevoir ce message. Nous effectuerons une opération intéressante avec html
les données qui ont été transmises. Dans ce cas, nous allons simplement l'échouer via une notification de bureau,
il est tout à fait possible d'utiliser ce code HTML en toute sécurité dans l'interface utilisateur de l'extension. Insertion via
innerHTML
ne présente pas de risque de sécurité important, même la compromission totale du système de bac à sable.
le code par le biais d'attaques intelligentes serait incapable d'injecter du contenu de script ou de plug-in dangereux dans
le contexte des extensions
à autorisation élevée.
Ce mécanisme facilite la création de modèles, mais ne se limite évidemment pas à la création de modèles. N'importe quelle valeur tout code qui ne fonctionne pas directement avec une Content Security Policy stricte peut être exécuté en bac à sable. dans Il est souvent utile de mettre en bac à sable les composants de vos extensions qui fonctionnent correctement. pour restreindre chaque élément de votre programme au plus petit ensemble de droits s’exécuter correctement. La présentation Écrire des applications Web et des extensions Chrome sécurisées de Google L'édition 2012 de Google I/O 2012 donne de bons exemples concrets de ces techniques et dure 56 minutes de votre en temps réel.