@@ -105,6 +105,28 @@ describe('object', () => {
105105 expect ( schema . validate ( new Test ( ) ) . value ) . to . be . instanceof ( Test ) ;
106106 } ) ;
107107
108+ it ( 'does not pollute the cloned value prototype via a __proto__ key' , ( ) => {
109+
110+ const schema = Joi . object ( { name : Joi . string ( ) } ) ;
111+
112+ const payload = JSON . parse ( '{"name":"alice","__proto__":{"isAdmin":true,"role":"superuser"}}' ) ;
113+ expect ( Object . getPrototypeOf ( payload ) ) . to . equal ( Object . prototype ) ;
114+ expect ( payload . isAdmin ) . to . not . exist ( ) ;
115+
116+ const { value, error } = schema . validate ( payload ) ;
117+ expect ( error ) . to . not . exist ( ) ;
118+ expect ( Object . getPrototypeOf ( value ) ) . to . equal ( Object . prototype ) ;
119+ expect ( value . isAdmin ) . to . not . exist ( ) ;
120+ expect ( value . role ) . to . not . exist ( ) ;
121+
122+ // Same with allowUnknown disabled
123+
124+ const { value : value2 , error : error2 } = schema . validate ( payload , { allowUnknown : false } ) ;
125+ expect ( error2 ) . to . not . exist ( ) ;
126+ expect ( Object . getPrototypeOf ( value2 ) ) . to . equal ( Object . prototype ) ;
127+ expect ( value2 . isAdmin ) . to . not . exist ( ) ;
128+ } ) ;
129+
108130 it ( 'allows any key when schema is undefined' , ( ) => {
109131
110132 Helper . validate ( Joi . object ( ) , [ [ { a : 4 } , true ] ] ) ;
@@ -3031,6 +3053,27 @@ describe('object', () => {
30313053 Helper . validate ( Joi . compile ( schema ) , [ [ { other : 'here' , A : 100 , c : 50 } , true , { other : 'here' , A : 100 , b : 100 , c : 50 } ] ] ) ;
30323054 } ) ;
30333055
3056+ it ( 'errors on a template target rendering __proto__ instead of setting the prototype' , ( ) => {
3057+
3058+ const payload = JSON . parse ( '{"user":"alice","x-__proto__":{"isAdmin":true,"role":"superuser"}}' ) ;
3059+
3060+ const schema = Joi . object ( { user : Joi . string ( ) . required ( ) } )
3061+ . rename ( / ^ x - ( .+ ) $ / , Joi . x ( '{#1}' ) , { multiple : true } )
3062+ . unknown ( false ) ;
3063+
3064+ const { value, error } = schema . validate ( payload ) ;
3065+ expect ( error ) . to . be . an . error ( '"value" cannot rename "x-__proto__" because target "__proto__" is a reserved key' ) ;
3066+ expect ( error . details [ 0 ] . type ) . to . equal ( 'object.rename.proto' ) ;
3067+ expect ( Object . getPrototypeOf ( value ) ) . to . equal ( Object . prototype ) ;
3068+ expect ( value . isAdmin ) . to . not . exist ( ) ;
3069+ expect ( Object . prototype . isAdmin ) . to . not . exist ( ) ;
3070+
3071+ const { value : value2 , error : error2 } = schema . validate ( payload , { abortEarly : false } ) ;
3072+ expect ( error2 . details [ 0 ] . type ) . to . equal ( 'object.rename.proto' ) ;
3073+ expect ( Object . getPrototypeOf ( value2 ) ) . to . equal ( Object . prototype ) ;
3074+ expect ( value2 . isAdmin ) . to . not . exist ( ) ;
3075+ } ) ;
3076+
30343077 it ( 'uses template' , ( ) => {
30353078
30363079 const schema = Joi . object ( )
0 commit comments