Skip assigning __proto__ instead of rejecting it during validation

master
Sven Slootweg 3 years ago
parent d30fce96a8
commit 34d3ca7763

@ -11,6 +11,13 @@ const forbidSpecialProperties = require("./validators/forbid-special-properties"
const isErrorConstructor = require("./validators/is-error-constructor"); const isErrorConstructor = require("./validators/is-error-constructor");
const isContextSchema = require("./validators/is-context-schema"); const isContextSchema = require("./validators/is-context-schema");
function safeAssign(a, ... rest) {
let previousPrototype = a.__proto__;
Object.assign(a, ... rest);
a.__proto__ = previousPrototype;
return a;
}
module.exports = function createCustomErrorType(_name, _options) { module.exports = function createCustomErrorType(_name, _options) {
let [ name, options ] = validateArguments(arguments, { let [ name, options ] = validateArguments(arguments, {
name: [ required, isString ], name: [ required, isString ],
@ -48,7 +55,7 @@ module.exports = function createCustomErrorType(_name, _options) {
} }
ErrorConstructor._assignDefaultProperties(this); ErrorConstructor._assignDefaultProperties(this);
Object.assign(this, context); safeAssign(this, context);
}; };
ErrorConstructor._assignDefaultProperties = function (errorObject) { ErrorConstructor._assignDefaultProperties = function (errorObject) {
@ -58,7 +65,7 @@ module.exports = function createCustomErrorType(_name, _options) {
options.inheritsFrom._assignDefaultProperties(errorObject); options.inheritsFrom._assignDefaultProperties(errorObject);
} }
Object.assign(errorObject, options.context); safeAssign(errorObject, options.context);
}; };
ErrorConstructor.prototype = Object.create(options.inheritsFrom.prototype); ErrorConstructor.prototype = Object.create(options.inheritsFrom.prototype);

@ -6,13 +6,12 @@ const syncpipe = require("syncpipe");
const wrapError = require("@validatem/wrap-error"); const wrapError = require("@validatem/wrap-error");
const forbidden = require("@validatem/forbidden"); const forbidden = require("@validatem/forbidden");
const allowExtraProperties = require("@validatem/allow-extra-properties"); const allowExtraProperties = require("@validatem/allow-extra-properties");
const ValidationError = require("@validatem/error");
const reservedProperties = require("../../reserved-properties"); const reservedProperties = require("../../reserved-properties");
let forbidSpecialProperty = wrapError("Reserved property name cannot be used", forbidden); let forbidSpecialProperty = wrapError("Reserved property name cannot be used", forbidden);
let baseChecks = syncpipe(reservedProperties, [ module.exports = syncpipe(reservedProperties, [
(_) => _.filter((property) => property !== "constructor"), (_) => _.filter((property) => property !== "constructor"),
(_) => _.map((property) => { (_) => _.map((property) => {
// NOTE: It is very important that `forbidSpecialProperty` below is wrapped in an array. Otherwise, for the `__proto__` property, it will actually treat the entire rules object as a validatem-special object due to its __proto__ being set directly to an object with the validatem-special marker... We're hacking around this by wrapping it in an array instead, which will not register as such. It's really a hack, though. // NOTE: It is very important that `forbidSpecialProperty` below is wrapped in an array. Otherwise, for the `__proto__` property, it will actually treat the entire rules object as a validatem-special object due to its __proto__ being set directly to an object with the validatem-special marker... We're hacking around this by wrapping it in an array instead, which will not register as such. It's really a hack, though.
@ -21,12 +20,3 @@ let baseChecks = syncpipe(reservedProperties, [
(_) => fromEntries(_), (_) => fromEntries(_),
(_) => allowExtraProperties(_) (_) => allowExtraProperties(_)
]); ]);
module.exports = [
baseChecks,
(value) => {
if (value.__proto__ != null) {
return new ValidationError("Reserved property name __proto__ cannot be used");
}
}
];

Loading…
Cancel
Save