我想使用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;
}
看:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in