Lookup for vulnerable packages by Package URL.

Purlpkg:npm/next-intl@4.0.0-beta-c40c5c9
Typenpm
Namespace
Namenext-intl
Version4.0.0-beta-c40c5c9
Qualifiers
Subpath
Is_vulnerabletrue
Next_non_vulnerable_version4.9.2
Latest_non_vulnerable_version4.9.2
Affected_by_vulnerabilities
0
url VCID-pk34-81rc-nye4
vulnerability_id VCID-pk34-81rc-nye4
summary next-intl: next-intl: Open Redirect vulnerability allows off-site redirection via crafted URLs
references
0
reference_url https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2026-40299.json
reference_id
reference_type
scores
0
value 4.3
scoring_system cvssv3
scoring_elements CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
url https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2026-40299.json
1
reference_url https://api.first.org/data/v1/epss?cve=CVE-2026-40299
reference_id
reference_type
scores
0
value 0.00059
scoring_system epss
scoring_elements 0.18637
published_at 2026-06-09T12:55:00Z
1
value 0.00059
scoring_system epss
scoring_elements 0.18737
published_at 2026-06-05T12:55:00Z
2
value 0.00059
scoring_system epss
scoring_elements 0.1874
published_at 2026-06-06T12:55:00Z
3
value 0.00059
scoring_system epss
scoring_elements 0.18699
published_at 2026-06-07T12:55:00Z
4
value 0.00059
scoring_system epss
scoring_elements 0.18619
published_at 2026-06-08T12:55:00Z
url https://api.first.org/data/v1/epss?cve=CVE-2026-40299
2
reference_url https://github.com/amannn/next-intl
reference_id
reference_type
scores
0
value 6.9
scoring_system cvssv4
scoring_elements CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
1
value MODERATE
scoring_system generic_textual
scoring_elements
url https://github.com/amannn/next-intl
3
reference_url https://github.com/amannn/next-intl/commit/1c80b668aa6d853f470319eec10a3f61e78a70e6
reference_id
reference_type
scores
0
value 6.9
scoring_system cvssv4
scoring_elements CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
1
value MODERATE
scoring_system generic_textual
scoring_elements
2
value Track
scoring_system ssvc
scoring_elements SSVCv2/E:N/A:Y/T:P/P:M/B:A/M:M/D:T/2026-04-20T15:56:01Z/
url https://github.com/amannn/next-intl/commit/1c80b668aa6d853f470319eec10a3f61e78a70e6
4
reference_url https://github.com/amannn/next-intl/pull/2304
reference_id
reference_type
scores
0
value 6.9
scoring_system cvssv4
scoring_elements CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
1
value MODERATE
scoring_system generic_textual
scoring_elements
2
value Track
scoring_system ssvc
scoring_elements SSVCv2/E:N/A:Y/T:P/P:M/B:A/M:M/D:T/2026-04-20T15:56:01Z/
url https://github.com/amannn/next-intl/pull/2304
5
reference_url https://github.com/amannn/next-intl/releases/tag/v4.9.1
reference_id
reference_type
scores
0
value 6.9
scoring_system cvssv4
scoring_elements CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
1
value MODERATE
scoring_system generic_textual
scoring_elements
2
value Track
scoring_system ssvc
scoring_elements SSVCv2/E:N/A:Y/T:P/P:M/B:A/M:M/D:T/2026-04-20T15:56:01Z/
url https://github.com/amannn/next-intl/releases/tag/v4.9.1
6
reference_url https://github.com/amannn/next-intl/security/advisories/GHSA-8f24-v5vv-gm5j
reference_id
reference_type
scores
0
value MODERATE
scoring_system cvssv3.1_qr
scoring_elements
1
value 6.9
scoring_system cvssv4
scoring_elements CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
2
value MODERATE
scoring_system generic_textual
scoring_elements
3
value Track
scoring_system ssvc
scoring_elements SSVCv2/E:N/A:Y/T:P/P:M/B:A/M:M/D:T/2026-04-20T15:56:01Z/
url https://github.com/amannn/next-intl/security/advisories/GHSA-8f24-v5vv-gm5j
7
reference_url https://nvd.nist.gov/vuln/detail/CVE-2026-40299
reference_id
reference_type
scores
0
value 6.9
scoring_system cvssv4
scoring_elements CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
1
value MODERATE
scoring_system generic_textual
scoring_elements
url https://nvd.nist.gov/vuln/detail/CVE-2026-40299
8
reference_url https://bugzilla.redhat.com/show_bug.cgi?id=2459333
reference_id 2459333
reference_type
scores
url https://bugzilla.redhat.com/show_bug.cgi?id=2459333
9
reference_url https://github.com/advisories/GHSA-8f24-v5vv-gm5j
reference_id GHSA-8f24-v5vv-gm5j
reference_type
scores
0
value MODERATE
scoring_system cvssv3.1_qr
scoring_elements
url https://github.com/advisories/GHSA-8f24-v5vv-gm5j
fixed_packages
0
url pkg:npm/next-intl@4.9.1
purl pkg:npm/next-intl@4.9.1
is_vulnerable true
affected_by_vulnerabilities
0
vulnerability VCID-w7z1-kpga-6uft
resource_url http://public2.vulnerablecode.io/packages/pkg:npm/next-intl@4.9.1
aliases CVE-2026-40299, GHSA-8f24-v5vv-gm5j
risk_score 3.1
exploitability 0.5
weighted_severity 6.2
resource_url http://public2.vulnerablecode.io/vulnerabilities/VCID-pk34-81rc-nye4
1
url VCID-w7z1-kpga-6uft
vulnerability_id VCID-w7z1-kpga-6uft
summary
next-intl has prototype pollution with `experimental.messages.precompile` via attacker-controlled translation catalog keys
## Summary

`setNestedProperty` in `packages/next-intl/src/extractor/utils.tsx` walks a dotted key path and assigns the final value without blocking the reserved keys `__proto__`, `constructor`, or `prototype`. When the next-intl Next.js plugin is configured with `experimental.messages` and `messages.precompile: true`, a JSON translation catalog containing a top‑level `__proto__` key causes `setNestedProperty(result, '__proto__.isAdmin', compiledMessage)` to assign onto `Object.prototype`, polluting every object in the running build process.

## Details

Root cause — `packages/next-intl/src/extractor/utils.tsx:13-34`:

```ts
export function setNestedProperty(
  obj: Record<string, any>,
  keyPath: string,
  value: any
): void {
  const keys = keyPath.split('.');
  let current = obj;

  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];
    if (
      !(key in current) ||
      typeof current[key] !== 'object' ||
      current[key] === null
    ) {
      current[key] = {};
    }
    current = current[key];
  }

  current[keys[keys.length - 1]] = value;
}
```

The existence check `!(key in current)` uses the `in` operator, which walks the prototype chain. For `key === '__proto__'`, `'__proto__' in {}` is `true` (it's inherited from `Object.prototype`) and `typeof current['__proto__'] === 'object'` (it *is* `Object.prototype`). The guard therefore never re-initializes `current[key]`, and `current = current['__proto__']` redirects all subsequent writes onto `Object.prototype`. The final assignment `current[keys[keys.length-1]] = value` sets `Object.prototype[<attacker key>] = <attacker value>`.

Build-time data flow:

1. `packages/next-intl/src/plugin/catalog/catalogLoader.tsx:55-83` — the webpack/turbopack loader receives the catalog file `source` and, if `options.messages.precompile` is enabled, calls `codec.decode(source, {locale})`.
2. `packages/next-intl/src/extractor/format/codecs/JSONCodec.tsx:9-18` — `decode` runs `JSON.parse(source)`. V8 installs `__proto__` as an **own data property** on the result when the JSON key is literally `"__proto__"` (bypassing the normal `Object.prototype.__proto__` setter that would otherwise reassign the prototype).
3. `JSONCodec.tsx:33-53` — `traverseMessages` iterates `Object.keys(obj)`, which for a JSON‑parsed object includes the own `__proto__` key. It reads `obj.__proto__` (returns the attacker’s nested object, not `Object.prototype`, because it's an own property), recurses into it, and emits message id `__proto__.isAdmin`.
4. `catalogLoader.tsx:71` — `precompileMessages(decoded, cache)`.
5. `catalogLoader.tsx:89-131` — for each message, calls `setNestedProperty(result, message.id, compiledMessage)`. With `message.id === '__proto__.isAdmin'`, `setNestedProperty` walks into `Object.prototype` and assigns `Object.prototype.isAdmin = compiledMessage`.

The same sink is also reachable via `JSONCodec.encode` (`JSONCodec.tsx:20-26`) and `POCodec` (`packages/next-intl/src/extractor/format/codecs/POCodec.tsx:87`) during extraction, both of which feed attacker-influenced `message.id` values into `setNestedProperty` — but those paths require control of source-code identifiers, which is a weaker attack vector than the build-time catalog path above.

After pollution, every subsequent object access during the remainder of the Next.js build pipeline (webpack, turbopack, babel, next-intl’s own logic) inherits the attacker-controlled properties. This is a classic gadget-chain precondition for corrupting build-tool internals and tampering with generated bundles, since many build tools use patterns like `if (obj.someFlag)` or `options[key] ?? default` that are sensitive to polluted prototypes.

Trust boundary note: next-intl’s message catalogs are realistically attacker-influenced in practice. Translation files are routinely round-tripped through external TMS systems (Crowdin, Lokalise, Transifex), accepted via community locale PRs, or pulled from third-party translation packages — any of which can carry a crafted `__proto__` key unnoticed, since JSON translation diffs are usually merged with minimal scrutiny.

## PoC

Prerequisites: a Next.js project using next-intl ≤ 4.9.1 with the Next.js plugin configured:

```ts
// next.config.ts
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin({
  experimental: {
    messages: {
      path: './messages',
      format: 'json',
      locales: 'infer',
      precompile: true
    }
  }
});

export default withNextIntl({});
```

1. Drop a malicious catalog at `messages/en.json`:

   ```json
   {
     "Greeting": "Hello",
     "__proto__": { "isAdmin": "polluted" }
   }
   ```

2. Run `next build` (or `next dev`). The `catalogLoader` will invoke `JSONCodec.decode` → `traverseMessages` → `precompileMessages` → `setNestedProperty`.

3. Minimal reproduction of the sink itself (verified locally against the v4.9.1 source):

   ```js
   function setNestedProperty(obj, keyPath, value) {
     const keys = keyPath.split('.');
     let current = obj;
     for (let i = 0; i < keys.length - 1; i++) {
       const key = keys[i];
       if (!(key in current) || typeof current[key] !== 'object' || current[key] === null) {
         current[key] = {};
       }
       current = current[key];
     }
     current[keys[keys.length - 1]] = value;
   }

   setNestedProperty({}, '__proto__.isAdmin', 'PWNED');
   console.log(({}).isAdmin); // -> "PWNED"
   ```

   Output: `PWNED`.

4. Full chain reproduction (also verified):

   ```js
   const parsed = JSON.parse('{"Greeting":"Hello","__proto__":{"isAdmin":"polluted"}}');
   // traverseMessages emits: [{id:"Greeting",message:"Hello"},{id:"__proto__.isAdmin",message:"polluted"}]
   // precompileMessages then calls setNestedProperty(result, "__proto__.isAdmin", "polluted")
   console.log(({}).isAdmin); // -> "polluted"
   ```

   After the loader runs, `({}).isAdmin === 'polluted'` for the remainder of the build Node process.

## Impact

- `Object.prototype` is polluted for the lifetime of the build‑time Node.js process, affecting every object created or inspected thereafter in the Next.js build pipeline (webpack/turbopack loaders, babel plugins, next-intl’s own codecs, user plugins).
- Classic CWE-1321 gadget-chain precondition: downstream tools that branch on `obj.someFlag`, `options[key] ?? default`, `if (!config.noX)`, etc. can be coerced into unintended behavior, including emitting tampered bundles.
- Realistic delivery vectors include TMS round-trips (Crowdin/Lokalise/Transifex), community locale PRs, and compromised/transitively-installed translation packages — all situations where a JSON catalog diff is routinely accepted without the scrutiny given to code changes.
- Exploitation requires the user to opt in to the `experimental.messages` + `precompile` configuration. Users who do not use the extractor/precompile features are not affected.

## Recommended Fix

Reject reserved keys in `setNestedProperty` and stop using the `in` operator for the existence check. A minimal patch to `packages/next-intl/src/extractor/utils.tsx`:

```ts
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);

export function setNestedProperty(
  obj: Record<string, any>,
  keyPath: string,
  value: any
): void {
  const keys = keyPath.split('.');
  for (const key of keys) {
    if (FORBIDDEN_KEYS.has(key)) {
      throw new Error(`Invalid message id segment: ${key}`);
    }
  }

  let current = obj;
  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];
    if (
      !Object.prototype.hasOwnProperty.call(current, key) ||
      typeof current[key] !== 'object' ||
      current[key] === null
    ) {
      current[key] = Object.create(null);
    }
    current = current[key];
  }

  current[keys[keys.length - 1]] = value;
}
```

Additionally:

- In `packages/next-intl/src/extractor/format/codecs/JSONCodec.tsx`, make `traverseMessages` skip reserved keys (or switch to `Object.create(null)` + `Object.hasOwn` semantics) so that a malicious catalog is rejected early with a clear error rather than producing `__proto__.*` message ids.
- In `packages/next-intl/src/plugin/catalog/catalogLoader.tsx`, initialize `precompileMessages`’s `result` with `Object.create(null)` as defense in depth, so even if a key slipped through it could not redirect through `Object.prototype`.
references
0
reference_url https://github.com/amannn/next-intl
reference_id
reference_type
scores
0
value 4.2
scoring_system cvssv3.1
scoring_elements CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:L
1
value MODERATE
scoring_system generic_textual
scoring_elements
url https://github.com/amannn/next-intl
1
reference_url https://github.com/amannn/next-intl/security/advisories/GHSA-4c35-wcg5-mm9h
reference_id
reference_type
scores
0
value 4.2
scoring_system cvssv3.1
scoring_elements CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:L
1
value MODERATE
scoring_system cvssv3.1_qr
scoring_elements
2
value MODERATE
scoring_system generic_textual
scoring_elements
url https://github.com/amannn/next-intl/security/advisories/GHSA-4c35-wcg5-mm9h
2
reference_url https://github.com/advisories/GHSA-4c35-wcg5-mm9h
reference_id GHSA-4c35-wcg5-mm9h
reference_type
scores
0
value MODERATE
scoring_system cvssv3.1_qr
scoring_elements
url https://github.com/advisories/GHSA-4c35-wcg5-mm9h
fixed_packages
0
url pkg:npm/next-intl@4.9.2
purl pkg:npm/next-intl@4.9.2
is_vulnerable false
affected_by_vulnerabilities
resource_url http://public2.vulnerablecode.io/packages/pkg:npm/next-intl@4.9.2
aliases GHSA-4c35-wcg5-mm9h
risk_score 3.1
exploitability 0.5
weighted_severity 6.2
resource_url http://public2.vulnerablecode.io/vulnerabilities/VCID-w7z1-kpga-6uft
Fixing_vulnerabilities
Risk_score3.1
Resource_urlhttp://public2.vulnerablecode.io/packages/pkg:npm/next-intl@4.0.0-beta-c40c5c9