Nashorn原型污染可见性问题

Nashorn 里经典的 “原型污染可见性” 问题:

  1. 扩展了 Array.prototype.add = ...
  2. Nashorn 把 原型上的可枚举属性 也当成 数组元素 返回给 Java
  3. 于是 Java 侧拿到 Object[] 时,最后一个元素就是字符串 "add"

快速复现

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(
    "Array.prototype.add = function (v) {" +
    "  if (this.indexOf(v) == -1) this.push(v);" +
    "};" +
    "var a = [1, 2, 3];" +
    "a.add(4);" +
    "a;"
);
Object[] arr = (Object[]) engine.get("a");
System.out.println(Arrays.toString(arr));

输出:

[1, 2, 3, 4, add]

原因剖析

  • Nashorn 的 NativeArrayfor-in 枚举 时会 把原型链上可枚举属性一起列出(符合 ECMA-262 规范,但和浏览器默认行为不同)。
  • 当你把数组返回给 Java,内部走 JSObject::getOwnProperty(true) → 包含原型可枚举属性 → 被 Java 反射成元素。

解决方案(任选其一)

✅ 方案 1:定义成 不可枚举 属性(推荐)
Object.defineProperty(Array.prototype, 'add', {
  value: function (v) { if (this.indexOf(v) === -1) this.push(v); },
  enumerable: false,   // 关键
  writable: true,
  configurable: true
});

再执行,"add" 不再出现在 Object[] 里。

✅ 方案 2:返回前手动过滤(不改动原型)
var a = [1, 2, 3];
a.add(4);
// 只保留数字元素
var pure = a.filter(function (it) { return typeof it === 'number'; });
pure;   // 返回这个给 Java
✅ 方案 3:Java 侧过滤
Object[] arr = (Object[]) engine.eval("a;");
List<Object> list = Arrays.stream(arr)
                          .filter(o -> o instanceof Number)
                          .collect(Collectors.toList());

最后

给原型加方法时,务必 enumerable: false
否则 Nashorn 会把方法名当成数组元素暴露给 Java。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Brldy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值