File tree Expand file tree Collapse file tree 4 files changed +82
-2
lines changed Expand file tree Collapse file tree 4 files changed +82
-2
lines changed Original file line number Diff line number Diff line change @@ -134,3 +134,40 @@ test("key and value getters", () => {
134134 rec . valueSchema . parse ( 1234 ) ;
135135 rec . element . parse ( 1234 ) ;
136136} ) ;
137+
138+ test ( "is not vulnerable to prototype pollution" , async ( ) => {
139+ const rec = z . record (
140+ z . object ( {
141+ a : z . string ( ) ,
142+ } )
143+ ) ;
144+
145+ const data = JSON . parse ( `
146+ {
147+ "__proto__": {
148+ "a": "evil"
149+ },
150+ "b": {
151+ "a": "good"
152+ }
153+ }
154+ ` ) ;
155+
156+ const obj1 = rec . parse ( data ) ;
157+ expect ( obj1 . a ) . toBeUndefined ( ) ;
158+
159+ const obj2 = rec . safeParse ( data ) ;
160+ expect ( obj2 . success ) . toBe ( true ) ;
161+ if ( obj2 . success ) {
162+ expect ( obj2 . data . a ) . toBeUndefined ( ) ;
163+ }
164+
165+ const obj3 = await rec . parseAsync ( data ) ;
166+ expect ( obj3 . a ) . toBeUndefined ( ) ;
167+
168+ const obj4 = await rec . safeParseAsync ( data ) ;
169+ expect ( obj4 . success ) . toBe ( true ) ;
170+ if ( obj4 . success ) {
171+ expect ( obj4 . data . a ) . toBeUndefined ( ) ;
172+ }
173+ } ) ;
Original file line number Diff line number Diff line change @@ -136,7 +136,10 @@ export class ParseStatus {
136136 if ( key . status === "dirty" ) status . dirty ( ) ;
137137 if ( value . status === "dirty" ) status . dirty ( ) ;
138138
139- if ( typeof value . value !== "undefined" || pair . alwaysSet ) {
139+ if (
140+ key . value !== "__proto__" &&
141+ ( typeof value . value !== "undefined" || pair . alwaysSet )
142+ ) {
140143 finalObject [ key . value ] = value . value ;
141144 }
142145 }
Original file line number Diff line number Diff line change @@ -133,3 +133,40 @@ test("key and value getters", () => {
133133 rec . valueSchema . parse ( 1234 ) ;
134134 rec . element . parse ( 1234 ) ;
135135} ) ;
136+
137+ test ( "is not vulnerable to prototype pollution" , async ( ) => {
138+ const rec = z . record (
139+ z . object ( {
140+ a : z . string ( ) ,
141+ } )
142+ ) ;
143+
144+ const data = JSON . parse ( `
145+ {
146+ "__proto__": {
147+ "a": "evil"
148+ },
149+ "b": {
150+ "a": "good"
151+ }
152+ }
153+ ` ) ;
154+
155+ const obj1 = rec . parse ( data ) ;
156+ expect ( obj1 . a ) . toBeUndefined ( ) ;
157+
158+ const obj2 = rec . safeParse ( data ) ;
159+ expect ( obj2 . success ) . toBe ( true ) ;
160+ if ( obj2 . success ) {
161+ expect ( obj2 . data . a ) . toBeUndefined ( ) ;
162+ }
163+
164+ const obj3 = await rec . parseAsync ( data ) ;
165+ expect ( obj3 . a ) . toBeUndefined ( ) ;
166+
167+ const obj4 = await rec . safeParseAsync ( data ) ;
168+ expect ( obj4 . success ) . toBe ( true ) ;
169+ if ( obj4 . success ) {
170+ expect ( obj4 . data . a ) . toBeUndefined ( ) ;
171+ }
172+ } ) ;
Original file line number Diff line number Diff line change @@ -136,7 +136,10 @@ export class ParseStatus {
136136 if ( key . status === "dirty" ) status . dirty ( ) ;
137137 if ( value . status === "dirty" ) status . dirty ( ) ;
138138
139- if ( typeof value . value !== "undefined" || pair . alwaysSet ) {
139+ if (
140+ key . value !== "__proto__" &&
141+ ( typeof value . value !== "undefined" || pair . alwaysSet )
142+ ) {
140143 finalObject [ key . value ] = value . value ;
141144 }
142145 }
You can’t perform that action at this time.
0 commit comments