El sistema de extensiones de Chrome aplica una Política de Seguridad del Contenido (CSP) predeterminada bastante estricta.
Las restricciones de la política son claras: la secuencia de comandos se debe mover fuera de línea a otra
JavaScript, los controladores de eventos intercalados deben convertirse para usar addEventListener
, y eval()
es
inhabilitado. Las Apps de Chrome tienen una política aún más estricta, y estamos conformes con la seguridad
propiedades que proporcionan estas políticas.
Sin embargo, reconocemos que una variedad de bibliotecas usan construcciones similares a las de eval()
y eval
, como las siguientes:
new Function()
para optimizar el rendimiento y facilitar la expresión. Las bibliotecas de plantillas son
este estilo de implementación. Algunos (como Angular.js) admiten CSP
de inmediato, muchos frameworks populares aún no se actualizan a un mecanismo que sea compatible
extensiones' Un mundo sin eval
Por lo tanto, se ha demostrado que eliminar la compatibilidad con esa función es más
problemático de lo esperado.
En este documento, se presenta la zona de pruebas como un mecanismo seguro para incluir estas bibliotecas en tus proyectos. sin comprometer la seguridad. Para abreviar, utilizaremos el término extensiones en todo momento, pero porque el concepto se aplica de la misma forma a las aplicaciones.
¿Por qué usar una zona de pruebas?
eval
es peligroso dentro de una extensión porque el código que ejecuta tiene acceso a todo el contenido de la extensión.
con muchos permisos de la extensión. Hay una gran cantidad de APIs de chrome.*
potentes disponibles que podrían
tener un impacto grave en la seguridad y la privacidad del usuario el simple robo de datos es lo más importante.
La solución que se ofrece es una zona de pruebas en la que eval
puede ejecutar código sin acceder al
o las APIs de alto valor de la extensión. Sin datos, API ni problema.
Para ello, enumeramos archivos HTML específicos dentro del paquete de la extensión como zonas de pruebas.
Cuando se cargue una página de zona de pruebas, se moverá a un origen único y se denegará
acceso a las APIs de chrome.*
. Si cargamos esta página de zona de pruebas en nuestra extensión a través de un iframe
, podemos
pasar los mensajes, dejar que actúe sobre ellos de alguna manera y esperar a que nos envíe
resultado. Este mecanismo de mensajería sencillo nos brinda todo lo que necesitamos para incluir de forma segura el mensaje de eval
código en el flujo de trabajo de nuestra extensión.
Crear y usar una zona de pruebas.
Si quieres profundizar directamente en el código, toma la extensión de ejemplo de la zona de pruebas y realiza desactivadas. Es un ejemplo funcional de una pequeña API de mensajería compilada en Handlebars. de plantillas, y debería darte todo lo que necesitas para comenzar. Para aquellos que un poco más de explicación, analicemos ese ejemplo juntos.
Muestra una lista de archivos en el manifiesto
Cada archivo que deba ejecutarse dentro de una zona de pruebas debe incluirse en el manifiesto de la extensión agregando un
sandbox
. Este es un paso fundamental y es fácil de olvidar, así que vuelve a verificarlo.
tu archivo de zona de pruebas aparece en el manifiesto. En este ejemplo, estamos probando el archivo en una zona de pruebas inteligente.
llamada "sandbox.html". La entrada de manifiesto se ve de la siguiente manera:
{
...,
"sandbox": {
"pages": ["sandbox.html"]
},
...
}
Carga el archivo de la zona de pruebas
Para hacer algo interesante con el archivo de zona de pruebas, debemos cargarlo en un contexto en el que
se puede solucionar con el código de la extensión. Aquí, el archivo sandbox.html se cargó en la sección
la página del evento (eventpage.html) de la extensión por medio de un iframe
. eventpage.js contiene código
que envía un mensaje a la zona de pruebas cada vez que se hace clic en la acción del navegador buscando iframe
en la página y ejecutando el método postMessage
en su contentWindow
. El mensaje es un objeto
que contiene dos propiedades: context
y command
. Analizaremos ambas en un momento.
chrome.browserAction.onClicked.addListener(function() {
var iframe = document.getElementById('theFrame');
var message = {
command: 'render',
context: {thing: 'world'}
};
iframe.contentWindow.postMessage(message, '*');
});
postMessage
, consulta la documentación de postMessage
sobre MDN . Es bastante completo y vale la pena leerlo. En particular, ten en cuenta que los datos solo se pueden pasar de un lado a otro si se pueden serializar. Las funciones, por ejemplo, no lo son.Haz algo peligroso
Cuando se carga sandbox.html
, se carga la biblioteca de Handlebars, y se crea y compila una canalización
en la forma en que los Handlebars sugieren lo siguiente:
<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>
Esto no falla. Si bien Handlebars.compile
termina usando new Function
, las cosas funcionan
exactamente como se esperaba, y obtendremos una plantilla compilada en templates['hello']
.
Pasa el resultado
Esta plantilla estará disponible para su uso configurando un objeto de escucha de mensajes que acepte comandos.
en la página del evento. Usaremos el command
que se pasó para determinar lo que se debe hacer (podrías
imagina hacer más que simplemente renderizar; como crear plantillas. Quizás los administres en algún
?), y el context
se pasará a la plantilla directamente para su renderización. El HTML renderizado
se devolverá a la página del evento para que la extensión pueda realizar alguna acción útil más adelante:
<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>
Cuando vuelvas a la página Evento, recibiremos este mensaje y haremos algo interesante con el html
.
datos que se pasaron. En este caso, haremos el eco a través de una notificación de escritorio, pero
es completamente posible usar ese código HTML de forma segura como parte de la IU de la extensión. Insertarlo mediante
innerHTML
no representa un riesgo de seguridad significativo, ya que incluso un compromiso completo de la zona de pruebas
a través de algún ataque inteligente no podría insertar contenido peligroso de secuencias de comandos o complementos en
el contexto de la extensión de permisos altos.
Este mecanismo permite crear plantillas de forma sencilla, pero, por supuesto, no se limita a ese tipo de plantillas. Cualquiera El código que no funciona de inmediato bajo una política estricta de seguridad del contenido puede quedar en zona de pruebas. en De hecho, suele ser útil hacer una zona de pruebas de los componentes de las extensiones que podrían ejecutarse correctamente en orden restringir cada parte de tu programa al conjunto más pequeño de privilegios necesarios para que se ejecuten correctamente. La presentación sobre escritura de aplicaciones web seguras y extensiones de Chrome de Google I/O 2012 ofrece algunos buenos ejemplos de estas técnicas en acción. Vale 56 minutos tiempo.