Prototype Pollution
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.
| Package | Affected versions | Patched versions |
|---|---|---|
properties-readernpm | < 2.2.0 | 2.2.0 |
Affected products
2- properties-reader/properties-readerdescription
Patches
24e4bc392ecfdAllow for relying on Object prototype in steps of the expanded properties
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]
0877cc871db9Test case covering the use of `__proto__` as a section name
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- github.com/advisories/GHSA-jxvf-m3x5-mxwqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-28471ghsaADVISORY
- github.com/steveukx/properties/commit/0877cc871db9865f58dd9389ce99e61be05380a5ghsax_refsource_MISCWEB
- github.com/steveukx/properties/commit/4e4bc392ecfd0a128f48c1d69f64a0d7194fcaabghsaWEB
- github.com/steveukx/properties/issues/40ghsax_refsource_MISCWEB
- security.snyk.io/vuln/SNYK-JS-PROPERTIESREADER-1048968ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.