@@ -594,3 +594,59 @@ ObjectDefineProperties(regex, {
594594});
595595console.log(RegExpPrototypeSymbolReplace(regex, 'foo', 'a')); // 'faa'
596596```
597+
598+ ### Defining object own properties
599+
600+ When defining property descriptor (to add or update an own property to a
601+ JavaScript object), be sure to always use a null-prototype object to avoid
602+ prototype pollution.
603+
604+ ```js
605+ // User-land
606+ Object.prototype.get = function get() {};
607+
608+ // Core
609+ try {
610+ ObjectDefineProperty({}, 'someProperty', { value: 0 });
611+ } catch (err) {
612+ console.log(err); // TypeError: Invalid property descriptor.
613+ }
614+ ```
615+
616+ ```js
617+ // User-land
618+ Object.prototype.get = function get() {};
619+
620+ // Core
621+ ObjectDefineProperty({}, 'someProperty', { __proto__: null, value: 0 });
622+ console.log('no errors'); // no errors.
623+ ```
624+
625+ Same applies when trying to modify an existing property, e.g. trying to make a
626+ read-only property enumerable:
627+
628+ ```js
629+ // User-land
630+ Object.prototype.value = 'Unrelated user-provided data';
631+
632+ // Core
633+ class SomeClass {
634+ get readOnlyProperty() { return 'genuine data'; }
635+ }
636+ ObjectDefineProperty(SomeClass.prototype, 'readOnlyProperty', { enumerable: true });
637+ console.log(new SomeClass().readOnlyProperty); // Unrelated user-provided data
638+ ```
639+
640+ ```js
641+ // User-land
642+ Object.prototype.value = 'Unrelated user-provided data';
643+
644+ // Core
645+ const kEnumerableProperty = { __proto__: null, enumerable: true };
646+ // In core, use const {kEnumerableProperty} = require('internal/util');
647+ class SomeClass {
648+ get readOnlyProperty() { return 'genuine data'; }
649+ }
650+ ObjectDefineProperty(SomeClass.prototype, 'readOnlyProperty', kEnumerableProperty);
651+ console.log(new SomeClass().readOnlyProperty); // genuine data
652+ ```
0 commit comments