CVE-2026-48819 Overview
CVE-2026-48819 is a prototype pollution vulnerability [CWE-1321] in Hey API, an ecosystem that converts OpenAPI specifications into production-ready client SDKs. Versions prior to 0.97.3 ship a runtime template (dist/clients/core/params.ts) that is copied into generated SDKs as params.gen.ts. The buildClientParams function writes unknown slot-prefixed keys such as $body_, $headers_, $path_, and $query_ directly into the corresponding slot object. An attacker who controls parameter keys can supply $query___proto__ to pollute the prototype of the params.query object and inject inherited, attacker-controlled properties into for..in iteration.
Critical Impact
Attackers with control over parameter key names can pollute object prototypes in generated Hey API SDKs, altering downstream request construction and potentially influencing application logic that iterates over query, header, path, or body parameters.
Affected Products
- Hey API @hey-api/openapi-ts prior to 0.97.3
- Generated SDKs that bundle the params.gen.ts runtime template from affected versions
- Applications consuming the buildClientParams helper from dist/clients/core/params.ts
Discovery Timeline
- 2026-07-17 - CVE-2026-48819 published to NVD
- 2026-07-23 - Last updated in NVD database
Technical Details for CVE-2026-48819
Vulnerability Analysis
Hey API generates typed SDK clients from OpenAPI documents. The generated helper buildClientParams groups user-supplied inputs into named slots (body, headers, path, query) based on prefixed key names. The function accepts arbitrary sub-keys after the slot prefix and assigns them directly to the slot object without filtering reserved JavaScript property names. Because slot objects are created as ordinary object literals, their prototype chain is reachable through __proto__, constructor, and prototype keys.
Submitting $query___proto__ alongside a legitimate q field causes the assignment params["query"]["__proto__"] = value, which is equivalent to Object.setPrototypeOf(params.query, value). Any subsequent for..in traversal over params.query surfaces attacker-controlled inherited properties, which are then serialized into outbound HTTP requests.
Root Cause
The root cause is missing key sanitization in the slot-writing branch of buildClientParams. The generator trusts prefix-stripped key names and does not reject the reserved identifiers __proto__, constructor, and prototype. Combined with the use of plain object literals for slots, this permits prototype mutation via ordinary property assignment.
Attack Vector
Exploitation requires an application that forwards untrusted key names into buildClientParams. A remote attacker who can influence request key naming, for example through a proxy layer, forwarded webhook, or user-defined query mapping, can send crafted key names to pollute the generated SDK's slot prototypes and manipulate outbound API calls made by the host application.
// Security patch (initial mitigation) — introduces a denylist of unsafe sub-keys
// packages/openapi-ts/src/plugins/@hey-api/client-core/bundle/params.ts
};
const extraPrefixes = Object.entries(extraPrefixesMap);
+const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
+
type KeyMap = Map<
string,
| {
// Source: https://github.com/hey-api/hey-api/commit/023909137a15eff9c0263d3bcd116140076b214f
// Follow-up hardening — slot objects are created with a null prototype
// packages/openapi-ts/src/plugins/@hey-api/client-core/bundle/params.ts
};
const extraPrefixes = Object.entries(extraPrefixesMap);
-const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
-
type KeyMap = Map<
string,
| {
// Source: https://github.com/hey-api/hey-api/commit/da321a1529eb3c90d2109da870f514b915a60169
// The denylist is removed once slot objects are built via Object.create(null),
// which has no reachable prototype and cannot be polluted through property assignment.
Detection Methods for CVE-2026-48819
Indicators of Compromise
- Inbound requests containing parameter keys with __proto__, constructor, or prototype fragments, especially after the $body_, $headers_, $path_, or $query_ prefixes used by Hey API SDKs.
- Outbound HTTP requests from services using Hey API clients that carry unexpected query, header, or body fields not defined in the OpenAPI schema.
- Deployed applications still shipping params.gen.ts generated from @hey-api/openapi-ts versions below 0.97.3.
Detection Strategies
- Perform a repository-wide search for params.gen.ts and inspect the bundled buildClientParams implementation for the presence of the UNSAFE_KEYS guard or an Object.create(null) slot initializer.
- Add application-layer logging that records any parameter key matching /^\$(body|headers|path|query)_(_proto__|constructor|prototype)/ before it reaches SDK code.
- Review dependency manifests (package.json, package-lock.json, pnpm-lock.yaml) for @hey-api/openapi-ts versions older than 0.97.3.
Monitoring Recommendations
- Monitor web application firewalls and API gateways for query strings and JSON payloads carrying __proto__, constructor, or prototype tokens.
- Alert on Node.js runtime anomalies such as globally mutated Object.prototype properties surfaced during health checks or integration tests.
- Track outbound egress from services using generated Hey API clients for parameter drift versus the source OpenAPI specification.
How to Mitigate CVE-2026-48819
Immediate Actions Required
- Upgrade @hey-api/openapi-ts to version 0.97.3 or later and regenerate all downstream SDKs so the patched params.gen.ts is redeployed.
- Rebuild and redeploy any services that vendored the older generated client code, since the vulnerable template is copied at generation time.
- Audit application code that forwards untrusted key names into buildClientParams and reject reserved identifiers at the boundary.
Patch Information
The fix is delivered in @hey-api/openapi-ts@0.97.3. Commit 023909137a15eff9c0263d3bcd116140076b214f introduces an UNSAFE_KEYS denylist covering __proto__, constructor, and prototype. Commit da321a1529eb3c90d2109da870f514b915a60169 supersedes the denylist by constructing slot objects with Object.create(null), eliminating the reachable prototype chain. See the GitHub Security Advisory GHSA-hhx9-57xq-r5rw and the 0.97.3 release notes for full details.
Workarounds
- Wrap calls to buildClientParams with an input sanitizer that strips any key containing __proto__, constructor, or prototype before delegation.
- Freeze Object.prototype at application startup with Object.freeze(Object.prototype) to blunt the impact of prototype pollution until upgrade is possible.
- Restrict which upstream components can supply dynamic parameter keys to trusted, schema-validated sources.
# Upgrade Hey API and regenerate SDK output
npm install --save-dev @hey-api/openapi-ts@^0.97.3
npx @hey-api/openapi-ts \
--input ./openapi.yaml \
--output ./src/generated/client
# Verify the patched runtime is present
grep -R "Object.create(null)" ./src/generated/client/core/params.gen.ts
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

