我想使用一个JavaScript对象({}
)作为一个字典来存储不受信任的数据。(我知道有一个 Map
但如果说我不想使用 Map
.)
如果我写
let obj = {};
obj[key] = value;
哪儿 key
和 value
是由一个不受信任的来源提供的,什么键会导致令人惊讶的行为?
我知道,分配 obj.__proto__
可以改变对象的原型,从而改变对象的行为。这有时被称为 中毒原型.) 所以我可能应该排除 '__proto__'
:
let obj = {};
if (key !== '__proto__') {
obj[key] = value;
}
是否还有其他这样的不安全键,可以以某种方式改变对象的行为,或者说是否有其他的不安全键?'__proto__'
唯一的一个?
如果你引用ECMAScript规范或参考文档,就会得到奖励。
上的所有属性 Object.prototype
可能会导致问题的名称碰撞。
console.log(
Object.getOwnPropertyNames(Object.prototype)
);
就是这样
另一个不用担心名称碰撞的方法是制作一个对象,这个对象的名称是 不 继承 Object.prototype
例如
const obj = Object.create(null);
// Now, this is perfectly fine (though weird):
obj.__proto__ = 'foo';
console.log(obj.__proto__);
如果你只是简单地从原型中寻找排除现存的值,你可以使用两个检查的组合:
1) 他们试图设置的属性是否已经存在于对象中。
const exists = '__proto__' in obj; // Or whichever property name they are setting
2) 如果是的话,它是直接的属性,还是来自上游(例如,你可以允许他们直接在对象上设置覆盖现有的属性)。
const onSelf = obj.hasOwnProperty('__proto__'); // Or whichever property name they are setting
那么也许你的保护会是这样的。
if (!(key in obj) || obj.hasOwnProperty(key)) {
obj[key] = value;
}
参见: