VYPR
Moderate severityNVD Advisory· Published Mar 16, 2020· Updated Aug 4, 2024

CVE-2020-7608

CVE-2020-7608

Description

yargs-parser could be tricked into adding or modifying properties of Object.prototype using a "__proto__" payload.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

CVE-2020-7608 is a prototype pollution vulnerability in yargs-parser that allows remote code execution via a crafted `__proto__` payload.

CVE-2020-7608 is a prototype pollution vulnerability in the yargs-parser library, a popular command-line argument parser used by thousands of Node.js projects. The bug resides in how the parser handles property keys: it does not properly check for dangerous keys like __proto__, allowing an attacker to inject properties into Object.prototype when parsing crafted input [1][2].

Exploitation

To exploit this, an attacker can supply a --__proto__.polluted=true argument or embed __proto__ in a JSON-like string passed to the parser [1]. Authentication is not required — any application that exposes user-controlled command-line arguments or configuration strings to yargs-parser is at risk. This includes scenarios where server-side scripts process client-supplied arguments indirectly [2][3].

Impact

Successful prototype pollution can lead to denial of service (via exceptions) or, more critically, remote code execution. By polluting Object.prototype with properties that alter the application’s runtime behavior, an attacker may force the code down a malicious path. The vulnerability was assigned CVSSv3 score 9.8 (Critical) because it can be exploited remotely without user interaction [2][3].

Mitigation

The fix was released in yargs-parser version 13.1.2 and 15.0.1 (and later). Users should update to the latest patched version. The GitHub commit [4] and Snyk advisory [3] provide details. No workaround is available for older versions; updating is the only reliable mitigation.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
yargs-parsernpm
>= 6.0.0, < 13.1.213.1.2
yargs-parsernpm
>= 14.0.0, < 15.0.115.0.1
yargs-parsernpm
>= 16.0.0, < 18.1.118.1.1
yargs-parsernpm
< 5.0.15.0.1

Affected products

4

Patches

2
1c417bd0b42b

fix(security): address GHSA-p9pc-299p-vxgp (#362)

https://github.com/yargs/yargs-parserBenjamin E. CoeMar 10, 2021via ghsa
1 file changed · +15 0
  • .github/workflows/release-please.yml+15 0 added
    @@ -0,0 +1,15 @@
    +on:
    +   push:
    +     branches:
    +       - v5.x.x
    +name: release-please
    +jobs:
    +  release-please:
    +    runs-on: ubuntu-latest
    +    steps:
    +      - uses: google-github-actions/release-please-action@v2
    +        with:
    +          token: ${{ secrets.GITHUB_TOKEN }}
    +          release-type: node
    +          package-name: yargs-parser
    +          default-branch: v5.x.x
    
63810ca1ae1a

fix: __proto__ will now be replaced with ___proto___ in parse (#258)

https://github.com/yargs/yargs-parserBenjamin E. CoeMar 16, 2020via ghsa
3 files changed · +70 2
  • index.js+15 1 modified
    @@ -697,6 +697,10 @@ function parse (args, opts) {
         if (!configuration['dot-notation']) keys = [keys.join('.')]
     
         keys.slice(0, -1).forEach(function (key, index) {
    +      // TODO(bcoe): in the next major version of yargs, switch to
    +      // Object.create(null) for dot notation:
    +      key = sanitizeKey(key)
    +
           if (typeof o === 'object' && o[key] === undefined) {
             o[key] = {}
           }
    @@ -716,7 +720,10 @@ function parse (args, opts) {
           }
         })
     
    -    const key = keys[keys.length - 1]
    +    // TODO(bcoe): in the next major version of yargs, switch to
    +    // Object.create(null) for dot notation:
    +    const key = sanitizeKey(keys[keys.length - 1])
    +
         const isTypeArray = checkAllAliases(keys.join('.'), flags.arrays)
         const isValueArray = Array.isArray(value)
         let duplicate = configuration['duplicate-arguments-array']
    @@ -1001,4 +1008,11 @@ Parser.detailed = function (args, opts) {
       return parse(args.slice(), opts)
     }
     
    +// TODO(bcoe): in the next major version of yargs, switch to
    +// Object.create(null) for dot notation:
    +function sanitizeKey (key) {
    +  if (key === '__proto__') return '___proto___'
    +  return key
    +}
    +
     module.exports = Parser
    
  • test/fixtures/config.json+9 1 modified
    @@ -4,5 +4,13 @@
         "foo": "baz",
         "version": "1.0.2",
         "truthy": true,
    -    "toString": "method name"
    +    "toString": "method name",
    +    "__proto__": {
    +      "aaa": 99
    +    },
    +    "bar": {
    +      "__proto__": {
    +        "bbb": 100
    +      }
    +    }
     }
    
  • test/yargs-parser.js+46 0 modified
    @@ -727,6 +727,25 @@ describe('yargs-parser', function () {
     
           argv.error.message.should.equal('someone set us up the bomb')
         })
    +
    +    it('should not pollute the prototype', function () {
    +      const argv = parser(['--foo', 'bar'], {
    +        alias: {
    +          z: 'zoom'
    +        },
    +        default: {
    +          settings: jsonPath
    +        },
    +        config: 'settings'
    +      })
    +
    +      argv.should.have.property('herp', 'derp')
    +      argv.should.have.property('zoom', 55)
    +      argv.should.have.property('foo').and.deep.equal('bar')
    +
    +      expect({}.bbb).to.equal(undefined)
    +      expect({}.aaa).to.equal(undefined)
    +    })
       })
     
       describe('config objects', function () {
    @@ -974,6 +993,13 @@ describe('yargs-parser', function () {
           argv.f.foo.should.eql(99)
           argv.f.bar.should.eql(true)
         })
    +
    +    it('should not pollute the prototype', function () {
    +      parser(['-f.__proto__.foo', '99', '-x.y.__proto__.bar', '100', '--__proto__', '200'])
    +      Object.keys({}.__proto__).length.should.equal(0) // eslint-disable-line
    +      expect({}.foo).to.equal(undefined)
    +      expect({}.bar).to.equal(undefined)
    +    })
       })
     
       it('should set boolean and alias using explicit true', function () {
    @@ -3702,4 +3728,24 @@ describe('yargs-parser', function () {
           argv._.should.eql([101, 102])
         })
       })
    +
    +  it('should replace the key __proto__ with the key ___proto___', function () {
    +    const argv = parser(['-f.__proto__.foo', '99', '-x.y.__proto__.bar', '100', '--__proto__', '200'])
    +    argv.should.eql({
    +      _: [],
    +      ___proto___: 200,
    +      f: {
    +        ___proto___: {
    +          foo: 99
    +        }
    +      },
    +      x: {
    +        y: {
    +          ___proto___: {
    +            bar: 100
    +          }
    +        }
    +      }
    +    })
    +  })
     })
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.