Vulnerabilities in pkg:npm/valibot

PACKAGE
Advisory Identifier: GHSA-5qjj-4xww-7phc
Advisory Summary

CVE-2026-59952 is a MODERATE record() issue paths can make vulnerability (CWE-755: Improper Handling of Exceptional Conditions) affecting Valibot libraries in the npm ecosystem. The issue involves record() issue paths can make flatten() throw for inherited object property names. Remediation is available by upgrading affected packages to version 1.4.2.

2 Known Advisory Record(s)
Package Vulnerability Intelligence

pkg:npm/valibot

2 Known Advisory Record(s)

Vulnerability advisories affecting package pkg:npm/valibot. Select an advisory below to view technical details or fixes.

Advisory ID CVE / NVD Severity Summary
GHSA-5qjj-4xww-7phc CVE-2026-59952 MODERATE Valibot: record() issue paths can make flatten() throw for inherited Object property names
GHSA-vqpr-j7v3-hqw9 CVE-2025-66020 HIGH Valibot has a ReDoS vulnerability in `EMOJI_REGEX`

CVE-2026-59952 at a Glance

CVE Identifier CVE-2026-59952
GHSA Identifier GHSA-5qjj-4xww-7phc
Severity MODERATE
CVSS v3.1 Base Score N/A
CWE Classification CWE-755: Improper Handling of Exceptional Conditions
Affected Product Valibot
Package Ecosystem npm
Published Date
Last Updated

How to Fix CVE-2026-59952

To remediate this vulnerability, upgrade all affected Valibot dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

valibot fixed: 1.4.2
npm install valibot@1.4.2
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls valibot

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2026-59952, inspect your project dependencies using npm:

npm ls valibot

Analyze the terminal output to locate any version of Valibot in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.4.2), your application is affected.

Note: The npm ls valibot command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-755: Improper Handling of Exceptional Conditions, where the product does not handle or incorrectly handles an exceptional condition. In Valibot, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## 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: ```ts 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: ```ts flatErrors.nested = {}; ``` For a dot path such as `toString`, this check reads the inherited `Object.prototype.toString` function: ```ts 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: ```bash npm install valibot@1.4.1 node poc_record_flatten_inherited_key_dos.mjs ``` Minimal example: ```js 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 `valibot@1.4.1`: ```json { "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 exception for `valueOf`, `hasOwnProperty`, `isPrototypeOf`, `propertyIsEnumerable`, and `toLocaleString`. A control case with an ordinary key produces normal flattened errors. ## Duplicate checks performed before submission - npm metadata confirmed current `valibot` release is `1.4.1` and maps to `open-circle/valibot`. - `gh api repos/open-circle/valibot/private-vulnerability-reporting` returned `{"enabled":true}`. - `npm audit` for a clean project containing only `valibot@1.4.1` returned no vulnerabilities. - Repository advisories and the GitHub Advisory Database only returned the historical emoji ReDoS advisory fixed in `1.2.0`. - OSV exact-version query for npm `valibot` `1.4.1` returned no vulnerabilities. - Public issue/PR searches for `flatten toString`, `flatten hasOwnProperty`, `record toString`, `__proto__`, `constructor`, and `prototype pollution` did not find a matching disclosure of this `record()` issue-path / `flatten()` exception. - Reviewed related public PRs: `open-circle/valibot#67` added prototype pollution mitigation for `record()` by blacklisting `__proto__`, `prototype`, and `constructor`; it does not cover `flatten()` collisions with other inherited property names. `open-circle/valibot#1429` is an open plain-object / `record()` type semantics PR and does not disclose this `flatten()` exception behavior. ## Suggested remediation Use null-prototype containers for flat error maps and/or perform own-property checks before appending: - Initialize `flatErrors.nested` as `Object.create(null)`. - Check nested entries with `Object.prototype.hasOwnProperty.call(flatErrors.nested, dotPath)` rather than truthiness. - Consider filtering or escaping unsafe dot path segments in `getDotPath()` / `flatten()`, including inherited Object property names. - Add regression tests for `flatten()` with paths `toString`, `valueOf`, `hasOwnProperty`, `__proto__`, `prototype`, and `constructor`. - Consider using the same hardening for other accumulator objects that store attacker-controlled keys.

CVE-2026-59952 Affected Valibot Versions

1 component(s)
Fixed Versions:
1.4.2
Product / Package Ecosystem Affected Versions Fixed Version
valibot
npm
< 1.4.2
1.4.2

References

Frequently Asked Questions

What is CVE-2026-59952?
CVE-2026-59952 is a security vulnerability in Valibot involving record() issue paths can make flatten() throw for inherited Object property names under CWE-755: Improper Handling of Exceptional Conditions.
Which Valibot versions are affected?
Affected versions include releases prior to 1.4.2 across affected packages: valibot.
What version fixes CVE-2026-59952?
Upgrading to 1.4.2 (or the latest patched release for your respective branch) resolves the vulnerability.
Is valibot affected?
Yes, valibot is affected in releases prior to 1.4.2. Upgrade your dependency to 1.4.2 or later.
What CWE is associated with CVE-2026-59952?
CVE-2026-59952 is classified under CWE-755: Improper Handling of Exceptional Conditions (The product does not handle or incorrectly handles an exceptional condition.).
How can I check npm dependencies for CVE-2026-59952?
Run the dependency tree command: 'npm ls valibot'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-5qjj-4xww-7phc",
  "modified" : "2026-07-24T16:14:31Z",
  "published" : "2026-07-24T16:14:31Z",
  "aliases" : [ "CVE-2026-59952" ],
  "summary" : "Valibot: record() issue paths can make flatten() throw for inherited Object property names",
  "details" : "## Summary\n\n`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`.\n\nThe 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.\n\nThis 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.\n\n## Affected package\n\n- Ecosystem: npm\n- Package: `valibot`\n- Affected version verified: `1.4.1`\n- Fixed version: none known\n- Repository: `open-circle/valibot`\n- Current main ref tested by source review: `9bb6617`\n\n## Root cause\n\n`record()` uses `_isValidObjectKey()` before validating record entries. The helper blocks the three classic prototype pollution keys:\n\n```ts\nkey !== '__proto__' &&\nkey !== 'prototype' &&\nkey !== 'constructor'\n```\n\nIt 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.\n\n`flatten()` then creates nested error storage with an ordinary object:\n\n```ts\nflatErrors.nested = {};\n```\n\nFor a dot path such as `toString`, this check reads the inherited `Object.prototype.toString` function:\n\n```ts\nif (flatErrors.nested![dotPath]) {\n  flatErrors.nested![dotPath]!.push(issue.message);\n}\n```\n\nBecause the inherited function is truthy, `flatten()` calls `.push(...)` on a function and throws `TypeError: flatErrors.nested[dotPath].push is not a function`.\n\n## Impact\n\nA remote attacker can trigger this if an application:\n\n1. validates attacker-controlled JSON objects with `v.record(...)`;\n2. receives an invalid key or invalid value under a key such as `toString`;\n3. uses Valibot's `flatten(result.issues)` helper to prepare validation errors.\n\nThis 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.\n\nThe 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.\n\n## Local reproduction\n\nRun in a disposable directory:\n\n```bash\nnpm install valibot@1.4.1\nnode poc_record_flatten_inherited_key_dos.mjs\n```\n\nMinimal example:\n\n```js\nimport * as v from 'valibot';\n\nconst schema = v.record(v.string(), v.number());\nconst input = JSON.parse('{\"toString\":\"not-a-number\"}');\n\nconst result = v.safeParse(schema, input);\nconsole.log(result.success); // false\nconsole.log(result.issues[0].path.map((item) => item.key)); // [\"toString\"]\n\nv.flatten(result.issues); // TypeError\n```\n\nObserved output from `valibot@1.4.1`:\n\n```json\n{\n  \"name\": \"record value schema rejects attacker-controlled value\",\n  \"key\": \"toString\",\n  \"success\": false,\n  \"issueCount\": 1,\n  \"firstPath\": [\"toString\"],\n  \"firstMessage\": \"Invalid type: Expected number but received \\\"not-a-number\\\"\",\n  \"flattened\": {\n    \"ok\": false,\n    \"exception\": \"TypeError\",\n    \"message\": \"flatErrors.nested[dotPath].push is not a function\"\n  }\n}\n```\n\nThe local PoC also reproduces the same exception for `valueOf`, `hasOwnProperty`, `isPrototypeOf`, `propertyIsEnumerable`, and `toLocaleString`. A control case with an ordinary key produces normal flattened errors.\n\n## Duplicate checks performed before submission\n\n- npm metadata confirmed current `valibot` release is `1.4.1` and maps to `open-circle/valibot`.\n- `gh api repos/open-circle/valibot/private-vulnerability-reporting` returned `{\"enabled\":true}`.\n- `npm audit` for a clean project containing only `valibot@1.4.1` returned no vulnerabilities.\n- Repository advisories and the GitHub Advisory Database only returned the historical emoji ReDoS advisory fixed in `1.2.0`.\n- OSV exact-version query for npm `valibot` `1.4.1` returned no vulnerabilities.\n- Public issue/PR searches for `flatten toString`, `flatten hasOwnProperty`, `record toString`, `__proto__`, `constructor`, and `prototype pollution` did not find a matching disclosure of this `record()` issue-path / `flatten()` exception.\n- Reviewed related public PRs: `open-circle/valibot#67` added prototype pollution mitigation for `record()` by blacklisting `__proto__`, `prototype`, and `constructor`; it does not cover `flatten()` collisions with other inherited property names. `open-circle/valibot#1429` is an open plain-object / `record()` type semantics PR and does not disclose this `flatten()` exception behavior.\n\n## Suggested remediation\n\nUse null-prototype containers for flat error maps and/or perform own-property checks before appending:\n\n- Initialize `flatErrors.nested` as `Object.create(null)`.\n- Check nested entries with `Object.prototype.hasOwnProperty.call(flatErrors.nested, dotPath)` rather than truthiness.\n- Consider filtering or escaping unsafe dot path segments in `getDotPath()` / `flatten()`, including inherited Object property names.\n- Add regression tests for `flatten()` with paths `toString`, `valueOf`, `hasOwnProperty`, `__proto__`, `prototype`, and `constructor`.\n- Consider using the same hardening for other accumulator objects that store attacker-controlled keys.",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "valibot"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.4.2"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 1.4.1"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/open-circle/valibot/security/advisories/GHSA-5qjj-4xww-7phc"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/open-circle/valibot/pull/1522"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/open-circle/valibot/commit/1bd01c304657cd0809cc92694360b6cc60f700bf"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/open-circle/valibot"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/open-circle/valibot/releases/tag/v1.4.2"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-755" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-24T16:14:31Z",
    "nvd_published_at" : null
  }
}