设置函数默认值

Set function default this value

背景:

我是 运行 一个只有 "allow-scripts" 权限的沙盒 iframe。在沙箱中,脚本加载了用户提供的自定义 js。现在我想像 XMLHttpRequest 一样管理对全局 functions/objects 的访问。目前我通过以下代码实现了这一点:

const CLEARED_WINDOW_SCOPE= {};
const scope = { /* Here goes the globals the script should have access too */};
const propertyNames = Object.getOwnPropertyNames(window);

for(let property of propertyNames){
    CLEARED_WINDOW_SCOPE[property] = undefined;
}

with(CLEARED_WINDOW_SCOPE){
    with(scope){
        (function (window, self, frames, globalThis){
            ${scriptContent}
        }).call(scope, scope, scope, scope, scope); 
    }
}

该脚本执行以下操作:

  1. 创建所有 window 属性 名称未定义的对象
  2. 使用用户也应有权访问的所有属性创建对象
  3. 用两个 with 语句包装用户代码,第一个清除所有全局变量,第二个获取定义的全局变量
  4. scope 作为 this
  5. 调用的函数包装用户代码

到目前为止,一切正常,一切正常。

问题:

我现在遇到的主要问题是,当用户定义这样的函数时:

function aFunction(){
   console.log(this);
}

他可以访问正常的 window 对象,因为函数中的默认 this 值是 window.

问题:

是否可以通过某种方式将函数的默认 this 值更改为周围作用域的 this 值。由于用户创建了脚本,我无法用 aFunction.bind(scope) 包装所有函数调用。或者是否有任何其他值可以防止访问全局 window 对象?

Is it somehow possible to change the default this value of a function to the this value of the surrounding scope.

不,但您可以做次优(?)的事情:将其设置为 undefined。强制严格模式:

"use strict";

// User's code
(function (){
  console.log(this)
})();

此外,我不是 JavaScript 安全专家,但 JS 沙箱是一个非常复杂的主题,因为原型污染等问题。

编辑:CherryDT noted in the comments, this method is not completely secure. Users can still access the <iframe> window by creating a function with the Function constructor, for example. Also, a reference to the main window can be obtained through the <iframe> window (window.parent).

将此解决方案用于 用户提供的 代码可能没问题(因为用户只需打开 DevTools 控制台并开始输入),但要确保代码来自 [=例如,36=]用户 而不是来自 URL 搜索参数。如果代码完全不受信任,我建议使用像 Google Caja.

这样的知名库