VYPR
Medium severity5.3OSV Advisory· Published Sep 24, 2025· Updated Apr 15, 2026

CVE-2025-57353

CVE-2025-57353

Description

The Runtime components of messageformat package for Node.js before 3.0.2 contain a prototype pollution vulnerability. Due to insufficient validation of nested message keys during the processing of message data, an attacker can manipulate the prototype chain of JavaScript objects by providing specially crafted input. This can result in the injection of arbitrary properties into the Object.prototype, potentially leading to denial of service conditions or unexpected application behavior. The vulnerability allows attackers to alter the prototype of base objects, impacting all subsequent object instances throughout the application's lifecycle.

AI Insight

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

Prototype pollution vulnerability in messageformat Node.js package before 3.0.2 allows attackers to inject properties into Object.prototype via crafted message keys, leading to DoS or unexpected behavior.

Vulnerability

Details

The @messageformat/runtime package, part of the messageformat monorepo for Node.js, contains a prototype pollution vulnerability (CWE-1321) in its Messages class. The addMessages method fails to validate nested message keys, allowing an attacker to use keys such as __proto__ to inject properties into Object.prototype [1][4]. This occurs because the library directly assigns nested objects without ensuring that the keys do not traverse the prototype chain [3].

Exploitation

An attacker can exploit this by providing specially crafted message data to an application that uses the vulnerable runtime components. The input can include nested key paths that reference __proto__, causing the library to set properties on the global object prototype [1][4]. No special privileges are required; any application that processes user-supplied messages (e.g., localization files or dynamic message definitions) is at risk.

Impact

Successful prototype pollution can lead to denial of service by corrupting object prototypes, causing unexpected application behavior or crashes. Additionally, it can broaden the attack surface for other prototype pollution exploits, as all objects in the application inherit the polluted properties [1][4].

Mitigation

The vulnerability is fixed in version 3.0.2 of the @messageformat/runtime package [3]. Users should update to this version or later. The fix introduces a _withNullPrototype helper that ensures nested objects are created with a null prototype, preventing prototype chain manipulation [3]. The messageformat project is available on GitHub [2].

AI Insight generated on May 19, 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
@messageformat/runtimenpm
>= 3.0.1, < 3.0.23.0.2

Affected products

1

Patches

2
3e5b24afddda

chore: Publish

4 files changed · +24 5
  • mf1/packages/core/package.json+1 1 modified
    @@ -33,7 +33,7 @@
         "@messageformat/date-skeleton": "2.0.0-0",
         "@messageformat/number-skeleton": "2.0.0-0",
         "@messageformat/parser": "^5.1.0",
    -    "@messageformat/runtime": "^3.0.1",
    +    "@messageformat/runtime": "^3.0.2",
         "make-plural": "^7.0.0",
         "safe-identifier": "^0.4.1"
       },
    
  • mf1/packages/runtime/CHANGELOG.md+6 0 modified
    @@ -3,6 +3,12 @@
     All notable changes to this project will be documented in this file.
     See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
     
    +## [3.0.2](https://github.com/messageformat/messageformat/compare/@messageformat/runtime@3.0.1...@messageformat/runtime@3.0.2) (2025-10-30)
    +
    +### Bug Fixes
    +
    +* **runtime:** Avoid prototype pollution in `Messages.p.addMessages()` ([#464](https://github.com/messageformat/messageformat/issues/464))
    +
     ## [3.0.1](https://github.com/messageformat/messageformat/compare/@messageformat/runtime@3.0.0...@messageformat/runtime@3.0.1) (2022-02-06)
     
     ### Bug Fixes
    
  • mf1/packages/runtime/package.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "@messageformat/runtime",
    -  "version": "3.0.1",
    +  "version": "3.0.2",
       "description": "Runtime components of messageformat",
       "keywords": [
         "i18n",
    
  • package-lock.json+16 3 modified
    @@ -138,7 +138,7 @@
             "@messageformat/date-skeleton": "2.0.0-0",
             "@messageformat/number-skeleton": "2.0.0-0",
             "@messageformat/parser": "^5.1.0",
    -        "@messageformat/runtime": "^3.0.1",
    +        "@messageformat/runtime": "^3.0.2",
             "make-plural": "^7.0.0",
             "safe-identifier": "^0.4.1"
           }
    @@ -187,7 +187,7 @@
         },
         "mf1/packages/runtime": {
           "name": "@messageformat/runtime",
    -      "version": "3.0.1",
    +      "version": "3.0.2",
           "license": "MIT",
           "dependencies": {
             "make-plural": "^7.0.0"
    @@ -323,6 +323,7 @@
           "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
           "dev": true,
           "license": "MIT",
    +      "peer": true,
           "dependencies": {
             "@ampproject/remapping": "^2.2.0",
             "@babel/code-frame": "^7.27.1",
    @@ -4313,6 +4314,7 @@
           "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
           "dev": true,
           "license": "MIT",
    +      "peer": true,
           "dependencies": {
             "@babel/parser": "^7.20.7",
             "@babel/types": "^7.20.7",
    @@ -4443,6 +4445,7 @@
           "integrity": "sha512-iAFpG6DokED3roLSP0K+ybeDdIX6Bc0Vd3mLW5uDqThPWtNos3E+EqOM11mPQHKzfWHqEBuLjIlsBQQ8CsISmQ==",
           "dev": true,
           "license": "MIT",
    +      "peer": true,
           "dependencies": {
             "undici-types": "~6.21.0"
           }
    @@ -4559,6 +4562,7 @@
           "integrity": "sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg==",
           "dev": true,
           "license": "MIT",
    +      "peer": true,
           "dependencies": {
             "@typescript-eslint/scope-manager": "8.39.0",
             "@typescript-eslint/types": "8.39.0",
    @@ -5090,6 +5094,7 @@
           "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
           "dev": true,
           "license": "MIT",
    +      "peer": true,
           "bin": {
             "acorn": "bin/acorn"
           },
    @@ -5629,6 +5634,7 @@
             }
           ],
           "license": "MIT",
    +      "peer": true,
           "dependencies": {
             "caniuse-lite": "^1.0.30001726",
             "electron-to-chromium": "^1.5.173",
    @@ -6317,6 +6323,7 @@
           "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==",
           "dev": true,
           "license": "MIT",
    +      "peer": true,
           "dependencies": {
             "@eslint-community/eslint-utils": "^4.2.0",
             "@eslint-community/regexpp": "^4.12.1",
    @@ -8019,6 +8026,7 @@
           "integrity": "sha512-d+DjBQ1tIhdz91B79mywH5yYu76bZuE96sSbxj8MkjWVx5WNdt1deEFRONVL4UkKLSrAbMkdhb24XN691yDRHg==",
           "dev": true,
           "license": "MIT",
    +      "peer": true,
           "dependencies": {
             "chalk": "^4.1.2",
             "graceful-fs": "^4.2.11",
    @@ -9373,6 +9381,7 @@
           "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
           "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
           "license": "MIT",
    +      "peer": true,
           "engines": {
             "node": ">=12"
           },
    @@ -9599,6 +9608,7 @@
           "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
           "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
           "license": "MIT",
    +      "peer": true,
           "dependencies": {
             "loose-envify": "^1.1.0"
           },
    @@ -9889,6 +9899,7 @@
           "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==",
           "devOptional": true,
           "license": "MIT",
    +      "peer": true,
           "dependencies": {
             "@types/estree": "1.0.8"
           },
    @@ -10603,7 +10614,8 @@
           "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
           "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
           "dev": true,
    -      "license": "0BSD"
    +      "license": "0BSD",
    +      "peer": true
         },
         "node_modules/type-check": {
           "version": "0.4.0",
    @@ -10697,6 +10709,7 @@
           "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
           "dev": true,
           "license": "Apache-2.0",
    +      "peer": true,
           "bin": {
             "tsc": "bin/tsc",
             "tsserver": "bin/tsserver"
    
82cd10b40e3f

fix(mf1): Avoid prototype pollution in @messageformat/runtime/messages (#464)

2 files changed · +22 8
  • mf1/packages/runtime/src/messages.test.ts+8 0 modified
    @@ -139,3 +139,11 @@ it('addMessages', async () => {
       messages.addMessages(() => 'z', null, ['x', 'y']);
       expect(messages.get(['x', 'y'])).toBe('z');
     });
    +
    +it('prototype pollution', () => {
    +  messages.addMessages({ payload: 'polluted' }, 'en', [
    +    '__proto__',
    +    'injectedProp'
    +  ]);
    +  expect(({} as any).injectedProp).toBeUndefined();
    +});
    
  • mf1/packages/runtime/src/messages.ts+14 8 modified
    @@ -110,7 +110,7 @@ export default class Messages {
       constructor(msgData: { [key: string]: MessageData }, defaultLocale?: string) {
         Object.keys(msgData).forEach(lc => {
           if (lc !== 'toString') {
    -        this._data[lc] = msgData[lc];
    +        this._data[lc] = _withNullPrototype(msgData[lc]);
             if (defaultLocale === undefined) defaultLocale = lc;
           }
         });
    @@ -171,17 +171,12 @@ export default class Messages {
         keypath?: string[]
       ) {
         const lc = locale || String(this.locale);
    -    if (typeof data !== 'function') {
    -      data = Object.keys(data).reduce<MessageData>((map, key) => {
    -        if (key !== 'toString') map[key] = (data as MessageData)[key];
    -        return map;
    -      }, {});
    -    }
    +    data = _withNullPrototype(data);
         if (Array.isArray(keypath) && keypath.length > 0) {
           let parent = this._data[lc] as MessageData;
           for (let i = 0; i < keypath.length - 1; ++i) {
             const key = keypath[i];
    -        if (!parent[key]) parent[key] = {};
    +        if (!parent[key]) parent[key] = Object.create(null);
             parent = parent[key] as MessageData;
           }
           parent[keypath[keypath.length - 1]] = data;
    @@ -342,3 +337,14 @@ function _has(
       }
       return false;
     }
    +
    +function _withNullPrototype<T = MessageData | MessageFunction | string>(
    +  value: T
    +): T {
    +  if (!value || typeof value !== 'object') return value;
    +  const data: MessageData = Object.create(null);
    +  for (const [key, value_] of Object.entries(value)) {
    +    data[key] = _withNullPrototype(value_);
    +  }
    +  return data as T;
    +}
    

Vulnerability mechanics

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

References

7

News mentions

0

No linked articles in our index yet.