@@ -137,6 +137,18 @@ export const getByPath = function(obj, path, delimiter) {
137137 return obj ;
138138} ;
139139
140+ const isGetSafe = function ( obj , key ) {
141+ // Prevent prototype pollution
142+ // https://snyk.io/vuln/SNYK-JS-JSON8MERGEPATCH-1038399
143+ if ( key === 'constructor' && typeof obj [ key ] === 'function' ) {
144+ return false ;
145+ }
146+ if ( key === '__proto__' ) {
147+ return false ;
148+ }
149+ return true ;
150+ } ;
151+
140152export const setByPath = function ( obj , path , value , delimiter ) {
141153
142154 const keys = Array . isArray ( path ) ? path : path . split ( delimiter || '/' ) ;
@@ -146,15 +158,8 @@ export const setByPath = function(obj, path, value, delimiter) {
146158
147159 for ( ; i < last ; i ++ ) {
148160 const key = keys [ i ] ;
161+ if ( ! isGetSafe ( diver , key ) ) return obj ;
149162 const value = diver [ key ] ;
150- // Prevent prototype pollution
151- // https://snyk.io/vuln/SNYK-JS-JSON8MERGEPATCH-1038399
152- if ( key === 'constructor' && typeof value === 'function' ) {
153- return obj ;
154- }
155- if ( key === '__proto__' ) {
156- return obj ;
157- }
158163 // diver creates an empty object if there is no nested object under such a key.
159164 // This means that one can populate an empty nested object with setByPath().
160165 diver = value || ( diver [ key ] = { } ) ;
@@ -167,25 +172,21 @@ export const setByPath = function(obj, path, value, delimiter) {
167172
168173export const unsetByPath = function ( obj , path , delimiter ) {
169174
170- delimiter || ( delimiter = '/' ) ;
171-
172- var pathArray = Array . isArray ( path ) ? path . slice ( ) : path . split ( delimiter ) ;
173-
174- var propertyToRemove = pathArray . pop ( ) ;
175- if ( pathArray . length > 0 ) {
176-
177- // unsetting a nested attribute
178- var parent = getByPath ( obj , pathArray , delimiter ) ;
179- if ( parent ) {
180- delete parent [ propertyToRemove ] ;
181- }
182-
183- } else {
175+ const keys = Array . isArray ( path ) ? path : path . split ( delimiter || '/' ) ;
176+ const last = keys . length - 1 ;
177+ let diver = obj ;
178+ let i = 0 ;
184179
185- // unsetting a primitive attribute
186- delete obj [ propertyToRemove ] ;
180+ for ( ; i < last ; i ++ ) {
181+ const key = keys [ i ] ;
182+ if ( ! isGetSafe ( diver , key ) ) return obj ;
183+ const value = diver [ key ] ;
184+ if ( ! value ) return obj ;
185+ diver = value ;
187186 }
188187
188+ delete diver [ keys [ last ] ] ;
189+
189190 return obj ;
190191} ;
191192
0 commit comments