Cómo evitar errores de JavaScript relacionados con la seguridad

Adobe AIR 1.0 y posterior

Si se llama al código que no se puede utilizar en un entorno limitado debido a estas restricciones de seguridad, el tiempo de ejecución distribuye un error de JavaScript: “Adobe AIR runtime security violation for JavaScript code in the application security sandbox” (Infracción de seguridad del motor de ejecución de Adobe AIR para el código JavaScript en el entorno limitado de seguridad de la aplicación). Para evitar este error, siga estas prácticas de codificación.

Causas de errores de JavaScript relacionados con la seguridad

El código que se ejecuta en el entorno limitado de la aplicación está restringido de la mayoría de las operaciones que requieren evaluar y ejecutar cadenas una vez que el evento de documento load se ha desencadenado y se ha salido de cualquier controlador de evento load . Si se intentan utilizar los siguientes tipos de sentencias JavaScript que evalúan y ejecutan cadenas potencialmente no seguras, se generan errores de JavaScript:

Asignación de contenido de aplicación en un entorno limitado diferente

En la mayoría de los casos, puede reescribir o reestructurar una aplicación para evitar errores de JavaScript relacionados con la seguridad. Sin embargo, cuando no se puede rescribir ni reestructurar, se puede cargar el contenido de la aplicación en un entorno limitado diferente utilizando la técnica descrita en Carga de contenido de aplicación en un entorno limitado que no pertenece a la aplicación . Si dicho contenido también debe acceder a las API de AIR, se puede crear un puente de entorno limitado, como se describe en Definición de una interfaz de puente de entorno limitado .

Función eval()

En el entorno limitado de la aplicación, la función eval() solo se puede utilizar antes de un evento load de página o durante un controlador de evento load . Una vez que la página se haya cargado, las llamadas a eval() no ejecutarán el código. Sin embargo, en los siguientes casos se puede reescribir el código para evitar el uso de eval() .

Asignación de propiedades a un objeto

En lugar de analizar una cadena para crear el acceso a la propiedad:

eval("obj." + propName + " = " + val);

acceso a las propiedades con sintaxis de corchete:

obj[propName] = val;

Creación de una función con variables disponibles en el contexto

Reemplace sentencias como la siguiente:

function compile(var1, var2){ 
    eval("var fn = function(){ this."+var1+"(var2) }"); 
    return fn; 
}

con:

function compile(var1, var2){ 
    var self = this; 
    return function(){ self[var1](var2) }; 
}

Creación de un objeto utilizando el nombre de la clase como un parámetro de cadena

Considere una clase hipotética de JavaScript definida en el siguiente código:

var CustomClass =  
    { 
        Utils: 
        { 
            Parser: function(){ alert('constructor') } 
        }, 
        Data:  
        { 
         
        } 
    }; 
var constructorClassName = "CustomClass.Utils.Parser";

La manera más simple de crear una instancia sería utilizar eval() :

var myObj; 
eval('myObj=new ' + constructorClassName +'()')

Sin embargo, puede evitar la llamada a eval() analizando cada componente de la clase name y crear un nuevo objeto utilizando la sintaxis de corchete:

function getter(str) 
{ 
    var obj = window; 
    var names = str.split('.'); 
    for(var i=0;i<names.length;i++){ 
        if(typeof obj[names[i]]=='undefined'){ 
            var undefstring = names[0]; 
            for(var j=1;j<=i;j++) 
                undefstring+="."+names[j]; 
            throw new Error(undefstring+" is undefined"); 
        } 
        obj = obj[names[i]]; 
    } 
    return obj; 
}

Para crear la instancia, utilice:

try{ 
    var Parser = getter(constructorClassName); 
    var a = new Parser(); 
    }catch(e){ 
        alert(e); 
}

setTimeout() y setInterval()

Reemplace la cadena analizada como la función de controlador con un objeto o referencia de función. Por ejemplo, reemplace una sentencia como:

setTimeout("alert('Timeout')", 100);

con:

setTimeout(function(){alert('Timeout')}, 100); 

O bien, cuando la función requiere que el autor de llamada defina el objeto this , reemplace una sentencia como:

this.appTimer = setInterval("obj.customFunction();", 100);

con la siguiente:

var _self = this; 
this.appTimer = setInterval(function(){obj.customFunction.apply(_self);}, 100);

Constructor Function

Las llamadas a new Function(param, body) se pueden reemplazar con una declaración de función en línea o utilizar solo antes de que se haya controlado el evento de página load .

URL de JavaScript

El código definido en un vínculo utilizando el esquema de URL javascript: se omite en el entorno limitado de la aplicación. No se genera ningún error de JavaScript de seguridad. Se pueden reemplazar vínculos utilizando URL javascript:, como:

<a href="javascript:code()">Click Me</a>

con:

<a href="#" onclick="code()">Click Me</a>

Callbacks de eventos asignados a través de atributos onevent en sentencias innerHTML y outerHTML

Cuando se utiliza innerHTML o outerHTML para añadir elementos al DOM de un documento, se omite cualquier callback de evento dentro de la sentencia, como onclick o onmouseover . No se genera ningún error de seguridad. En cambio, se puede asignar un atributo id a los nuevos elementos y definir las funciones de callback de controlador de eventos utilizando el método addEventListener() .

Por ejemplo, dado un elemento de destino en un documento, como:

<div id="container"></div>

Reemplace las sentencias como:

document.getElementById('container').innerHTML =  
    '<a href="#" onclick="code()">Click Me.</a>';

con:

document.getElementById('container').innerHTML = '<a href="#" id="smith">Click Me.</a>'; 
document.getElementById('smith').addEventListener("click", function() { code(); });

Carga de archivos JavaScript desde fuera del directorio de instalación de la aplicación

No se permite la carga de archivos de script desde fuera del entorno limitado de la aplicación. No se genera ningún error de seguridad. Todos los archivos de script que se ejecutan en el entorno limitado de la aplicación se deben instalar en el directorio de la aplicación. Para utilizar scripts externos en una página, se debe asignar la página a un entorno limitado diferente. Consulte Carga de contenido de aplicación en un entorno limitado que no pertenece a la aplicación

document.write() y document.writeln()

Se omiten las llamadas a document.write() o document.writeln() después de que se haya controlado el evento de página load . No se genera ningún error de seguridad. Como alternativa, se puede cargar un nuevo archivo o reemplazar el cuerpo del documento utilizando técnicas de manipulación DOM.

XMLHttpRequests sincrónicos antes del evento load o durante un controlador de evento load

XMLHttpRequests sincrónicos iniciados antes del evento de página load o durante un controlador de eventos load no devuelven contenido. Se pueden iniciar XMLHttpRequests asíncronos pero no devuelven contenido hasta después del evento load . Después de que se haya controlado el evento load , los XMLHttpRequests sincrónicos se comportan normalmente.

Elementos de script creados dinámicamente

Se omiten los elementos de script creados dinámicamente, como cuando se crean con el método document.createElement() o innerHTML.