低代码平台禁用原生eval,采用new function构造纯净上下文执行表达式,显式传入受限变量与白名单函数,配合ast分析和正则过滤防范逃逸,实现动态能力与安全可控的平衡。

在低代码平台中,eval 类函数常被用于规则引擎、动态表单逻辑、条件判断和动作响应等场景,但直接使用 eval() 极易引发安全与维护问题。实际落地时,平台通常不依赖原始 eval,而是采用受控的动态执行机制——核心在于**明确界定执行上下文**,而非放任代码自由访问全局环境。
执行上下文必须隔离
低代码平台运行用户配置的表达式(如 “price > 100 && status === 'active'”),这些表达式需在限定变量范围内求值。若用原生 eval,它会默认访问当前作用域所有变量,可能意外读取或覆盖内部状态。正确做法是构造纯净上下文对象:
- 显式传入仅允许使用的数据,例如
{ user: { name, role }, order: { total, items } } - 禁止访问
window、document、localStorage等浏览器 API - 避免使用
with语句,因其会模糊作用域边界,已被现代引擎标记为严格模式禁用
用 new Function() 替代 eval
平台底层更倾向使用 new Function('ctx', 'return ' + expression),原因在于:
- 每次执行都在全新函数作用域中,不污染调用方变量
- 引擎可对生成函数做 JIT 编译,性能比
eval高 3–5 倍(V8 实测) - 参数名
ctx强制开发者意识到“只许从这个对象里取值”,天然形成上下文契约
例如:const fn = new Function('ctx', 'return ctx.user.role === "admin"');,调用时仅需 fn({ user: { role: 'admin' } })。
上下文需支持安全函数白名单
部分平台允许表达式调用基础函数(如 Math.round、String.includes),但必须显式注入,不可继承全局对象:
- 构建最小函数集:只暴露
{ Math: { round, floor, max }, String: { includes } } - 将函数挂载到上下文对象上,如
ctx.Math = { round: Math.round } - 禁止传入原型方法(如
__proto__、constructor),防止原型链污染
避免上下文逃逸的关键检查
即使做了封装,仍需防范表达式绕过限制。常见逃逸方式及应对:
-
通过
Function构造器再生代码:正则过滤字符串中/new\s+Function|Function\s*\(/i -
利用
eval或setTimeout字符串参数:静态 AST 分析或关键词拦截 - 访问闭包外变量:确保执行函数定义在严格模式下,且不引用外部词法环境
真正健壮的低代码平台,不会把“能否执行”交给 eval 决定,而是把“能访问什么”由上下文对象精确声明——这才是动态能力与安全可控的平衡点。











