@@ -9,6 +9,15 @@ const fs = require('fs')
9
9
const parseArgs = require ( 'yargs-parser' )
10
10
const cloneDeep = require ( 'lodash.clonedeep' )
11
11
12
+ // Forbidden key paths, for protection against prototype pollution
13
+ const FORBIDDEN_KEY_PATHS = [
14
+ '__proto__' ,
15
+ 'this.constructor.prototype' ,
16
+ ]
17
+
18
+ const ALLOWED_OPTION_STRICT = 'strict'
19
+ const ALLOWED_OPTION_WARN = 'warn'
20
+
12
21
function assert ( assertion , err_msg ) {
13
22
if ( ! assertion ) {
14
23
throw new Error ( err_msg )
@@ -69,9 +78,6 @@ const custom_converters = new Map()
69
78
70
79
const parsers_registry = { '*' : JSON . parse }
71
80
72
- const ALLOWED_OPTION_STRICT = 'strict'
73
- const ALLOWED_OPTION_WARN = 'warn'
74
-
75
81
function flatten ( obj , useProperties ) {
76
82
const stack = Object . keys ( obj )
77
83
let key
@@ -561,14 +567,18 @@ const convict = function convict(def, opts) {
561
567
* exist, they will be initialized to empty objects
562
568
*/
563
569
set : function ( k , v ) {
570
+ for ( const path of FORBIDDEN_KEY_PATHS ) {
571
+ if ( k . startsWith ( `${ path } .` ) ) {
572
+ return this
573
+ }
574
+ }
575
+
564
576
v = coerce ( k , v , this . _schema , this )
565
577
const path = k . split ( '.' )
566
578
const childKey = path . pop ( )
567
579
const parentKey = path . join ( '.' )
568
- if ( ! ( parentKey == '__proto__' || parentKey == 'constructor' || parentKey == 'prototype' ) ) {
569
- const parent = walk ( this . _instance , parentKey , true )
570
- parent [ childKey ] = v
571
- }
580
+ const parent = walk ( this . _instance , parentKey , true )
581
+ parent [ childKey ] = v
572
582
return this
573
583
} ,
574
584
0 commit comments