CVE-2022-21190 (JavaScript, published 2022-05-13T20:15Z)
Description: value: This affects the package convict before 6.2.3. This is a bypass of [CVE-2022-22143](https://security.snyk.io/vuln/SNYK-JS-CONVICT-2340604). The [fix](https://github.com/mozilla/node-convict/commit/3b86be087d8f14681a9c889d45da7fe3ad9cd880) introduced, relies on the startsWith method and does not prevent the vulnerability: before splitting the path, it checks if it starts with __proto__ or this.constructor.prototype. To bypass this check it's possible to prepend the dangerous paths with any string value followed by a dot, like for example foo.__proto__ or foo.this.constructor.prototype.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-1321 \u2014 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
The product receives input from an upstream component that specifies attributes that are to be initialized or updated in an object, but it does not properly control modifications of attributes of the object prototype.
Repository: https://github.com/mozilla/node-convict
Files changed:
CHANGELOG.md
packages/convict/src/main.js
packages/convict/test/prototype_pollution.test.js
Commit message: More more complete fix for prototype pollution

vulnerability first addressed in #384


Vulnerable code:
  '__proto__',
  'this.constructor.prototype',
      for (const path of FORBIDDEN_KEY_PATHS) {
        if (k.startsWith(`${path}.`)) {

Fixed code:
## [6.2.3] - 2022-05-07

### Fixed

- More more complete fix for prototype pollution vulnerability first addressed
  in #384 (Marc-Aurèle Darche @madarche, Snyk Security team)


  '__proto__.',
  'this.constructor.prototype.',
      for (const forbidden_key_path of FORBIDDEN_KEY_PATHS) {
        if (k.startsWith(forbidden_key_path) ||
            k.includes(`.${forbidden_key_path}`)) {

    config.set('this.__proto__.polluted_proto_root', 'Polluted!')
    expect({}).not.toHaveProperty('polluted_proto_root')

    config.set('this.__proto__.nested.polluted_proto_nested', 'Polluted!')
    expect({}).not.toHaveProperty('nested')
    expect({}).not.toHaveProperty('nested.polluted_proto_nested')

    config.set('foo.__proto__.polluted_proto_root', 'Polluted!')
    expect({}).not.toHaveProperty('polluted_proto_root')

    config.set('foo.__proto__.nested.polluted_proto_nested', 'Polluted!')
    expect({}).not.toHaveProperty('nested')
    expect({}).not.toHaveProperty('nested.polluted_proto_nested')

    config.set('this.this.constructor.prototype.polluted_constructor_prototype_root', 'Polluted!')
    expect({}).not.toHaveProperty('polluted_constructor_prototype_root')

    config.set('this.this.constructor.prototype.nested.polluted_constructor_prototype_nested', 'Polluted!')
    expect({}).not.toHaveProperty('nested')
    expect({}).not.toHaveProperty('nested.polluted_constructor_prototype_nested')

    config.set('foo.this.constructor.prototype.polluted_constructor_prototype_root', 'Polluted!')
    expect({}).not.toHaveProperty('polluted_constructor_prototype_root')

    config.set('foo.this.constructor.prototype.nested.polluted_constructor_prototype_nested', 'Polluted!')
    expect({}).not.toHaveProperty('nested')
    expect({}).not.toHaveProperty('nested.polluted_constructor_prototype_nested')