应避免在 eval 执行上下文中滥用变量,核心是通过机制隔离切断其对敏感作用域的隐式访问;需将 eval 移至空壳函数、用 new function 替代、杜绝字符串拼接、结构化表达式、远离敏感数据声明,并启用沙箱防护。

避免在 eval 执行上下文中滥用变量,核心是切断它对敏感作用域的隐式访问能力——不是靠“小心点”,而是靠机制隔离。
明确拒绝 eval 访问局部变量
eval 默认会钻进当前函数的作用域链,读写所有局部变量(包括 let、const、参数),这是最大风险源。真正有效的做法是:不把它放在任何含私有状态的函数里。
- 把
eval调用移出业务逻辑函数,放到一个空壳函数中,例如:function safeEval(code) { return eval(code); }—— 这样它只能看到全局,看不到外层的token、user、config等 - 若必须传入变量,不用作用域继承,改用显式参数封装:
用new Function('x', 'y', 'return ' + expr)替代eval,变量只来自你明确传入的实参
杜绝动态拼接 + eval 的组合
用户输入哪怕只参与字符串拼接,就等于把执行权交了出去。比如 eval('x > ' + userInput),攻击者填 0 || alert(1) 就能弹窗。
- 所有参与拼接的值,必须提前通过正则白名单校验(如
/^[0-9.]+$/),且长度、类型、范围全受限 - 更彻底的做法:完全不用拼接。把表达式拆成结构化数据,例如
{ op: 'gt', left: 'x', right: 10 },再由预定义函数映射执行
用 new Function 替代 eval(当需动态执行)
new Function 不继承调用者作用域,天然隔离局部变量,比 eval 安全得多。
- 它只链接全局作用域(或模块顶层),不会污染或读取你函数内的
let apiToken = 'xxx' - 可进一步限制:只允许传入必要参数,其余一律屏蔽
const calc = new Function('a', 'b', 'return a + b'); - 注意:仍要校验
a、b的来源;若参数本身含恶意代码(如"1; alert(1)"),new Function同样会执行
ESM 模块里别指望“自动防护”
ESM 的 import/export 对 eval 完全无效。模块顶层的 let secret = 'xxx',只要 eval 在同一模块里调用,就能直接读写。
- 不要在模块顶层或导出函数内写
eval - 敏感数据声明位置要远离
eval调用点,最好不在同一函数、甚至不同文件 - 真需要动态执行不可信代码,必须上沙箱:Node.js 用
vm2,浏览器用iframe+postMessage











