Every CVE Search/ Get API key

CVE-2026-59952

Valibot: record() issue paths can make flatten() throw for inherited Object property names

6.9 MediumFix available

Valibot helps validate data using a schema. Versions prior to 1.4.2 can throw a TypeError inside its flatten() helper when validation issues contain attacker-controlled object keys such as toString, valueOf, or hasOwnProperty. The issue is reachable through normal record() validation. record() intentionally filters proto, prototype, and constructor, but it still accepts other own keys that collide with inherited Object.prototype properties. If the record key schema or value schema rejects such an entry, Valibot creates an issue path containing that key. Passing the resulting issues to Valibot's documented flatten() helper causes flatErrors.nested[dotPath] to resolve to the inherited method instead of an own error array, and the helper calls .push(...) on that function. This is not a global prototype pollution issue. The impact is availability/error handling: applications that validate user-controlled objects with record() and flatten validation errors for API responses can crash the request path with a TypeError instead of returning structured validation errors. This issue has been fixed in version 1.4.2.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
Low

Exploit likelihood

0.38%Down 0.1 points since Jul 30, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.9

Valibot: record() issue paths can make flatten() throw for inherited Object property names

Valibot helps validate data using a schema. Versions prior to 1.4.2 can throw a TypeError inside its flatten() helper when validation issues contain attacker-controlled object keys such as toString, valueOf, or hasOwnProperty. The issue is reachable through normal record() validation. record() intentionally filters proto, prototype, and constructor, but it still accepts other own keys that collide with inherited Object.prototype properties. If the record key schema or value schema rejects such an entry, Valibot creates an issue path containing that key. Passing the resulting issues to Valibot's documented flatten() helper causes flatErrors.nested[dotPath] to resolve to the inherited method instead of an own error array, and the helper calls .push(...) on that function. This is not a global prototype pollution issue. The impact is availability/error handling: applications that validate user-controlled objects with record() and flatten validation errors for API responses can crash the request path with a TypeError instead of returning structured validation errors. This issue has been fixed in version 1.4.2.

Record
CVE-2026-59952
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-755
Updated
2026-11-02
EUVDEUVD-2026-50775 6.9

Valibot helps validate data using a schema. Versions prior to 1.4.2 can throw a TypeError inside its flatten() helper when validation issues contain attacker-controlled object keys such as toString, valueOf, or hasOwnProperty. The issue is reachable through normal record() validation. record() intentionally filters proto, prototype, and constructor, but it still accepts other own keys that collide with inherited Object.prototype properties. If the record key schema or value schema rejects such an entry, Valibot creates an issue path containing that key. Passing the resulting issues to Valibot's documented flatten() helper causes flatErrors.nested[dotPath] to resolve to the inherited method instead of an own error array, and the helper calls .push(...) on that function. This is not a global prototype pollution issue. The impact is availability/error handling: applications that validate user-controlled objects with record() and flatten validation errors for API responses can crash the request path with a TypeError instead of returning structured validation errors. This issue has been fixed in version 1.4.2.

Record
EUVD-2026-50775
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-5qjj-4xww-7phc 6.9

Valibot: record() issue paths can make flatten() throw for inherited Object property names

Summary

valibot 1.4.1 can throw a TypeError inside its flatten() helper when validation issues contain attacker-controlled object keys such as toString, valueOf, or hasOwnProperty.

The issue is reachable through normal record() validation. record() intentionally filters __proto__, prototype, and constructor, but it still accepts other own keys that collide with inherited Object.prototype properties. If the record key schema or value schema rejects such an entry, Valibot creates an issue path containing that key. Passing the resulting issues to Valibot's documented flatten() helper causes flatErrors.nested[dotPath] to resolve to the inherited method instead of an own error array, and the helper calls .push(...) on that function.

This is not a global prototype pollution issue. The impact is availability/error handling: applications that validate user-controlled objects with record() and flatten validation errors for API responses can crash the request path with a TypeError instead of returning structured validation errors.

Affected package

  • Ecosystem: npm
  • Package: valibot
  • Affected version verified: 1.4.1
  • Fixed version: none known
  • Repository: open-circle/valibot
  • Current main ref tested by source review: 9bb6617

Root cause

record() uses _isValidObjectKey() before validating record entries. The helper blocks the three classic prototype pollution keys:

key !== '__proto__' &&
key !== 'prototype' &&
key !== 'constructor'

It does not block other inherited Object.prototype names such as toString, valueOf, and hasOwnProperty. These remain valid own JSON object keys and can appear in issue paths when either the record key schema or value schema rejects the entry.

flatten() then creates nested error storage with an ordinary object:

flatErrors.nested = {};

For a dot path such as toString, this check reads the inherited Object.prototype.toString function:

if (flatErrors.nested![dotPath]) {
  flatErrors.nested![dotPath]!.push(issue.message);
}

Because the inherited function is truthy, flatten() calls .push(...) on a function and throws TypeError: flatErrors.nested[dotPath].push is not a function.

Impact

A remote attacker can trigger this if an application:

  1. validates attacker-controlled JSON objects with v.record(...);
  2. receives an invalid key or invalid value under a key such as toString;
  3. uses Valibot's flatten(result.issues) helper to prepare validation errors.

This is a common pattern in API/form validation: safeParse() collects issues and flatten() converts them into response-friendly error objects. Instead of a validation response, the request can hit an unexpected exception path.

The same root cause can also affect manually constructed issues or other schemas that place inherited Object property names into dot paths. I am reporting the record() path because it uses only public Valibot APIs and attacker-controlled JSON keys.

Local reproduction

Run in a disposable directory:

npm install [email protected]
node poc_record_flatten_inherited_key_dos.mjs

Minimal example:

import * as v from 'valibot';

const schema = v.record(v.string(), v.number());
const input = JSON.parse('{"toString":"not-a-number"}');

const result = v.safeParse(schema, input);
console.log(result.success); // false
console.log(result.issues[0].path.map((item) => item.key)); // ["toString"]

v.flatten(result.issues); // TypeError

Observed output from [email protected]:

{
  "name": "record value schema rejects attacker-controlled value",
  "key": "toString",
  "success": false,
  "issueCount": 1,
  "firstPath": ["toString"],
  "firstMessage": "Invalid type: Expected number but received \"not-a-number\"",
  "flattened": {
    "ok": false,
    "exception": "TypeError",
    "message": "flatErrors.nested[dotPath].push is not a function"
  }
}

The local PoC also reproduces the same…

Record
GHSA-5qjj-4xww-7phc
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-755
Updated
2026-11-02
NVD 6.9

Valibot helps validate data using a schema. Versions prior to 1.4.2 can throw a TypeError inside its flatten() helper when validation issues contain attacker-controlled object keys such as toString, valueOf, or hasOwnProperty. The issue is reachable through normal record() validation. record() intentionally filters proto, prototype, and constructor, but it still accepts other own keys that collide with inherited Object.prototype properties. If the record key schema or value schema rejects such an entry, Valibot creates an issue path containing that key. Passing the resulting issues to Valibot's documented flatten() helper causes flatErrors.nested[dotPath] to resolve to the inherited method instead of an own error array, and the helper calls .push(...) on that function. This is not a global prototype pollution issue. The impact is availability/error handling: applications that validate user-controlled objects with record() and flatten validation errors for API responses can crash the request path with a TypeError instead of returning structured validation errors. This issue has been fixed in version 1.4.2.

Record
CVE-2026-59952
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Weakness
CWE-755
Updated
2026-11-02
OSV 6.9

Valibot: record() issue paths can make flatten() throw for inherited Object property names

Valibot helps validate data using a schema. Versions prior to 1.4.2 can throw a TypeError inside its flatten() helper when validation issues contain attacker-controlled object keys such as toString, valueOf, or hasOwnProperty. The issue is reachable through normal record() validation. record() intentionally filters proto, prototype, and constructor, but it still accepts other own keys that collide with inherited Object.prototype properties. If the record key schema or value schema rejects such an entry, Valibot creates an issue path containing that key. Passing the resulting issues to Valibot's documented flatten() helper causes flatErrors.nested[dotPath] to resolve to the inherited method instead of an own error array, and the helper calls .push(...) on that function. This is not a global prototype pollution issue. The impact is availability/error handling: applications that validate user-controlled objects with record() and flatten validation errors for API responses can crash the request path with a TypeError instead of returning structured validation errors. This issue has been fixed in version 1.4.2.

Record
CVE-2026-59952
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-755
Updated
2026-11-02
OSVGHSA-5qjj-4xww-7phc 6.9

Valibot: record() issue paths can make flatten() throw for inherited Object property names

Summary

valibot 1.4.1 can throw a TypeError inside its flatten() helper when validation issues contain attacker-controlled object keys such as toString, valueOf, or hasOwnProperty.

The issue is reachable through normal record() validation. record() intentionally filters __proto__, prototype, and constructor, but it still accepts other own keys that collide with inherited Object.prototype properties. If the record key schema or value schema rejects such an entry, Valibot creates an issue path containing that key. Passing the resulting issues to Valibot's documented flatten() helper causes flatErrors.nested[dotPath] to resolve to the inherited method instead of an own error array, and the helper calls .push(...) on that function.

This is not a global prototype pollution issue. The impact is availability/error handling: applications that validate user-controlled objects with record() and flatten validation errors for API responses can crash the request path with a TypeError instead of returning structured validation errors.

Affected package

  • Ecosystem: npm
  • Package: valibot
  • Affected version verified: 1.4.1
  • Fixed version: none known
  • Repository: open-circle/valibot
  • Current main ref tested by source review: 9bb6617

Root cause

record() uses _isValidObjectKey() before validating record entries. The helper blocks the three classic prototype pollution keys:

key !== '__proto__' &&
key !== 'prototype' &&
key !== 'constructor'

It does not block other inherited Object.prototype names such as toString, valueOf, and hasOwnProperty. These remain valid own JSON object keys and can appear in issue paths when either the record key schema or value schema rejects the entry.

flatten() then creates nested error storage with an ordinary object:

flatErrors.nested = {};

For a dot path such as toString, this check reads the inherited Object.prototype.toString function:

if (flatErrors.nested![dotPath]) {
  flatErrors.nested![dotPath]!.push(issue.message);
}

Because the inherited function is truthy, flatten() calls .push(...) on a function and throws TypeError: flatErrors.nested[dotPath].push is not a function.

Impact

A remote attacker can trigger this if an application:

  1. validates attacker-controlled JSON objects with v.record(...);
  2. receives an invalid key or invalid value under a key such as toString;
  3. uses Valibot's flatten(result.issues) helper to prepare validation errors.

This is a common pattern in API/form validation: safeParse() collects issues and flatten() converts them into response-friendly error objects. Instead of a validation response, the request can hit an unexpected exception path.

The same root cause can also affect manually constructed issues or other schemas that place inherited Object property names into dot paths. I am reporting the record() path because it uses only public Valibot APIs and attacker-controlled JSON keys.

Local reproduction

Run in a disposable directory:

npm install [email protected]
node poc_record_flatten_inherited_key_dos.mjs

Minimal example:

import * as v from 'valibot';

const schema = v.record(v.string(), v.number());
const input = JSON.parse('{"toString":"not-a-number"}');

const result = v.safeParse(schema, input);
console.log(result.success); // false
console.log(result.issues[0].path.map((item) => item.key)); // ["toString"]

v.flatten(result.issues); // TypeError

Observed output from [email protected]:

{
  "name": "record value schema rejects attacker-controlled value",
  "key": "toString",
  "success": false,
  "issueCount": 1,
  "firstPath": ["toString"],
  "firstMessage": "Invalid type: Expected number but received \"not-a-number\"",
  "flattened": {
    "ok": false,
    "exception": "TypeError",
    "message": "flatErrors.nested[dotPath].push is not a function"
  }
}

The local PoC also reproduces the same…

Record
GHSA-5qjj-4xww-7phc
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-755
Updated
2026-11-02
OSVCLSA-2026-1789465861 No score

TuxCare security update for valibot (2 CVEs)

TuxCare rebuilt valibot to address 2 CVEs. Fixed in 0.41.0-tuxcare.1.

Record
CLSA-2026-1789465861
Updated
2026-11-02
OSVCLSA-2026-1792473247 No score

TuxCare security update for valibot (1 CVE)

TuxCare rebuilt valibot to address 1 CVE. Fixed in 1.2.0-tuxcare.1.

Record
CLSA-2026-1792473247
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
valibot
npm
through 1.4.1
1.4.2
valibot
TuxCare:npm
From an advisory covering 2 CVEs
0.41.0-tuxcare.0 up to 0.41.0-tuxcare.1, plus listed versions
0.41.0
0.41.0-tuxcare.1
valibot
TuxCare:npm
1.2.0-tuxcare.0 up to 1.2.0-tuxcare.1, plus listed versions
1.2.0
1.2.0-tuxcare.1
valibot
npm
before 1.4.2
1.4.2

History

History
RecordedChangedSources
affected, facts
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-59952 is a medium vulnerability (CVSS 6.9) in Open-circle Valibot, published July 24, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.38%, the 32nd percentile. Fixed in valibot 1.4.2.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open