VYPR
Critical severityNVD Advisory· Published Jul 25, 2022· Updated Sep 16, 2024

Prototype Pollution

CVE-2020-28471

Description

Properties-reader before 2.2.0 is vulnerable to Prototype Pollution, allowing attackers to inject arbitrary properties into Object.prototype via crafted input.

AI Insight

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

Properties-reader before 2.2.0 is vulnerable to Prototype Pollution, allowing attackers to inject arbitrary properties into Object.prototype via crafted input.

Vulnerability

The properties-reader npm package before version 2.2.0 is affected by a Prototype Pollution vulnerability [1][4]. The library processes .ini or .properties files and fails to properly sanitize property keys, allowing an attacker to pollute the global Object prototype by including a key like __proto__ or constructor.prototype [3]. This is a classic prototype pollution issue where the unsafe object merge or property definition by path can be exploited [4].

Exploitation

An attacker can trigger this vulnerability by providing a malicious properties file or string that contains a key such as __proto__.polluted with a value. When the library reads this input via methods like properties.read(), the polluted key is assigned to the base object's prototype [3][4]. No authentication is required if the attacker can supply the properties content, e.g., via a web application that reads user-uploaded configuration files. The attack is performed locally on the Node.js server, but can be triggered remotely if the application accepts untrusted property sources.

Impact

Successful exploitation allows the attacker to inject arbitrary properties into all JavaScript objects in the runtime, potentially leading to denial of service via unexpected exceptions, or more severely, remote code execution if the polluted properties affect subsequent code paths [4]. The impact depends on the application's usage of the properties object.

Mitigation

Users should upgrade to version 2.2.0 or later, which includes a fix for this vulnerability [2]. The commit 0877cc871db9865f58dd9389ce99e61be05380a5 addresses the issue by sanitizing property keys [2]. No workarounds are documented; upgrading is recommended.

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
properties-readernpm
< 2.2.02.2.0

Affected products

2

Patches

2
4e4bc392ecfd

Allow for relying on Object prototype in steps of the expanded properties

https://github.com/steveukx/propertiesSteve KingDec 30, 2020via ghsa
1 file changed · +1 1
  • src/properties-reader.js+1 1 modified
    @@ -217,7 +217,7 @@ PropertiesReader.prototype.set = function (key, value) {
           }
     
           if (!has(source, step)) {
    -         Object.defineProperty(source, step, { value: Object.create(null) });
    +         Object.defineProperty(source, step, { value: {} });
           }
     
           source = source[step]
    
0877cc871db9

Test case covering the use of `__proto__` as a section name

https://github.com/steveukx/propertiesSteve KingDec 30, 2020via ghsa
2 files changed · +36 1
  • src/properties-reader.js+8 1 modified
    @@ -2,6 +2,8 @@ const {readFileSync, statSync} = require('fs');
     const propertyAppender = require('./property-appender').propertyAppender;
     const propertyWriter = require('./property-writer').propertyWriter;
     
    +const has = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
    +
     const SECTION = Symbol('SECTION');
     
     function PropertiesReader (sourceFile, encoding, options = {}) {
    @@ -213,7 +215,12 @@ PropertiesReader.prototype.set = function (key, value) {
           if (expanded.length >= 1 && typeof source[step] === 'string') {
              source[step] = {'': source[step]};
           }
    -      source = (source[step] = source[step] || {});
    +
    +      if (!has(source, step)) {
    +         Object.defineProperty(source, step, { value: Object.create(null) });
    +      }
    +
    +      source = source[step]
        }
     
        if (typeof parsedValue === 'string' && typeof  source[expanded[0]] === 'object') {
    
  • test/fix-prototype-pollution.spec.js+28 0 added
    @@ -0,0 +1,28 @@
    +const {createTestContext} = require('./__fixtues__/create-test-context');
    +
    +const propertiesReader = require('../');
    +
    +describe('prototype-pollution', () => {
    +   let context;
    +
    +   beforeEach(async () => {
    +      context = await createTestContext();
    +   });
    +
    +   it('does not pollute global Object.prototype', async () => {
    +      const file = `
    +         [__proto__]
    +            polluted = polluted
    +            parsed = true
    +      `;
    +      const props = propertiesReader(await context.file('props.ini', file));
    +
    +      expect(({}).polluted).toBeUndefined();
    +      expect(props.path().__proto__.polluted).toBe('polluted');
    +      expect(props.getRaw('__proto__.polluted')).toBe('polluted');
    +      expect(props.get('__proto__.polluted')).toBe('polluted');
    +      expect(props.getRaw('__proto__.parsed')).toBe('true');
    +      expect(props.get('__proto__.parsed')).toBe(true);
    +   });
    +
    +});
    

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.