util: harden more built-in classes against prototype pollution · nodejs/node@a648e4c · GitHub
Skip to content

Commit a648e4c

Browse files
aduh95ruyadorno
authored andcommitted
util: harden more built-in classes against prototype pollution
PR-URL: #56225 Reviewed-By: Jordan Harband <ljharb@gmail.com> Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
1 parent 5c2e061 commit a648e4c

3 files changed

Lines changed: 67 additions & 4 deletions

File tree

lib/buffer.js

Lines changed: 9 additions & 1 deletion

lib/internal/util/inspect.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
const {
44
Array,
5+
ArrayBuffer,
6+
ArrayBufferPrototype,
57
ArrayIsArray,
8+
ArrayPrototype,
69
ArrayPrototypeFilter,
710
ArrayPrototypeForEach,
811
ArrayPrototypeIncludes,
@@ -29,6 +32,8 @@ const {
2932
FunctionPrototypeSymbolHasInstance,
3033
FunctionPrototypeToString,
3134
JSONStringify,
35+
Map,
36+
MapPrototype,
3237
MapPrototypeEntries,
3338
MapPrototypeGetSize,
3439
MathFloor,
@@ -68,6 +73,8 @@ const {
6873
SafeMap,
6974
SafeSet,
7075
SafeStringIterator,
76+
Set,
77+
SetPrototype,
7178
SetPrototypeGetSize,
7279
SetPrototypeValues,
7380
String,
@@ -93,6 +100,8 @@ const {
93100
SymbolPrototypeValueOf,
94101
SymbolToPrimitive,
95102
SymbolToStringTag,
103+
TypedArray,
104+
TypedArrayPrototype,
96105
TypedArrayPrototypeGetLength,
97106
TypedArrayPrototypeGetSymbolToStringTag,
98107
Uint8Array,
@@ -599,8 +608,13 @@ function isInstanceof(object, proto) {
599608

600609
// Special-case for some builtin prototypes in case their `constructor` property has been tampered.
601610
const wellKnownPrototypes = new SafeMap();
602-
wellKnownPrototypes.set(ObjectPrototype, { name: 'Object', constructor: Object });
611+
wellKnownPrototypes.set(ArrayPrototype, { name: 'Array', constructor: Array });
612+
wellKnownPrototypes.set(ArrayBufferPrototype, { name: 'ArrayBuffer', constructor: ArrayBuffer });
603613
wellKnownPrototypes.set(FunctionPrototype, { name: 'Function', constructor: Function });
614+
wellKnownPrototypes.set(MapPrototype, { name: 'Map', constructor: Map });
615+
wellKnownPrototypes.set(ObjectPrototype, { name: 'Object', constructor: Object });
616+
wellKnownPrototypes.set(SetPrototype, { name: 'Set', constructor: Set });
617+
wellKnownPrototypes.set(TypedArrayPrototype, { name: 'TypedArray', constructor: TypedArray });
604618

605619
function getConstructorName(obj, ctx, recurseTimes, protoProps) {
606620
let firstProto;
@@ -825,12 +839,12 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
825839
// Filter out the util module, its inspect function is special.
826840
maybeCustom !== inspect &&
827841
// Also filter out any prototype objects using the circular check.
828-
!(value.constructor && value.constructor.prototype === value)) {
842+
ObjectGetOwnPropertyDescriptor(value, 'constructor')?.value?.prototype !== value) {
829843
// This makes sure the recurseTimes are reported as before while using
830844
// a counter internally.
831845
const depth = ctx.depth === null ? null : ctx.depth - recurseTimes;
832846
const isCrossContext =
833-
proxy !== undefined || !(context instanceof Object);
847+
proxy !== undefined || !FunctionPrototypeSymbolHasInstance(Object, context);
834848
const ret = FunctionPrototypeCall(
835849
maybeCustom,
836850
context,

test/parallel/test-util-inspect.js

Lines changed: 41 additions & 0 deletions

0 commit comments

Comments
 (0)