防范函数提升篡改内置行为的关键是冻结原型链、启用严格模式、禁用动态执行、封装敏感api并结合环境隔离。需早期冻结object.prototype、array.prototype,密封function.prototype,全局启用"use strict",禁用eval和function构造器,对动态代码白名单校验,并用代理封装json.parse、settimeout等api,配合realms或vm.script实现上下文隔离。

防范攻击者通过函数声明提升(hoisting)篡改核心内置行为,关键在于阻断其获取原始构造器或原型对象的路径,而非仅靠语法检查。函数提升本身是语言特性,无法禁用,真正危险的是提升后利用 this、constructor 或隐式上下文访问全局对象。
冻结关键原型链,切断篡改入口
攻击常依赖 Array.prototype.push、Object.prototype.toString 等方法被动态重写。必须在脚本加载早期(如入口文件第一行)执行冻结:
-
Object.freeze(Object.prototype)—— 阻止新增/修改属性,包括toString、valueOf -
Object.freeze(Array.prototype)—— 防止覆盖push、map等高危方法 -
Object.seal(Function.prototype)—— 允许调用但禁止新增方法(如防止注入bind替代逻辑)
避免裸露全局上下文,限制 this 指向
函数提升后若在非严格模式下执行,this 默认指向全局对象(如 window 或 globalThis),成为绕过沙箱的跳板:
- 所有脚本启用
"use strict"—— 此时顶层函数中this为undefined,无法反射出全局对象 - 禁用
eval和Function构造器 —— 它们会创建新执行上下文,绕过作用域冻结 - 对动态代码执行(如模板字符串解析)做白名单校验,拒绝含
.constructor、__proto__的表达式
用封装层替代直接调用,隔离敏感 API
不依赖原生方法的行为一致性,而是提供受控代理:
- 重写
JSON.parse为只接受纯对象/数组,拒绝函数或原型属性 - 将
setTimeout封装为只允许传入函数字面量,禁止字符串参数(防eval) - 对
require(Node.js)或import()做路径白名单,拒绝动态拼接(如require('fs' + '.promises'))
结合运行时上下文隔离,从源头收窄权限
单靠代码层加固不够,需配合环境级防护:
- 在 VS Code 插件中启用
"untrustedWorkspaces": { "supported": false },拒绝不受信工作区执行 - Node.js 中使用
vm.Script时,明确传入空context,不继承global属性 - 浏览器环境优先采用
Realms(如通过realm.evaluate())而非eval,确保上下文完全独立











