Orval OpenAPI Codegen Arbitrary Code Execution via Malicious Spec (CVE-2026-23947)
by Boroeurn Prach · 2026-07-05
- Severity
- High
- CVE
- CVE-2026-23947
- Category
- misc
- Affected product
- Orval (OpenAPI-to-TypeScript client generator), version 7.10.0
- Affected versions
- Orval < 8.0.2 (fixed in 8.0.2)
- Disclosed
- 2026-07-05
- Patch status
- patched
Tags
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-01 |
| Author / Researcher | Boroeurn Prach |
| CVE / Advisory | CVE-2026-23947 |
| Category | misc |
| Severity | High |
| CVSS Score | Not specified in source |
| Status | PoC |
| Tags | orval, openapi, code-generation, arbitrary-code-execution, nodejs, supply-chain, typescript, build-tooling |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Orval (OpenAPI-to-TypeScript client generator), version 7.10.0 |
| Versions Affected | Orval < 8.0.2 (fixed in 8.0.2) |
| Language / Platform | Node.js / TypeScript build tooling |
| Authentication Required | No (requires the victim to run Orval against an attacker-controlled/untrusted OpenAPI spec) |
| Network Access Required | No (local build-time execution; spec can be delivered via any untrusted source) |
Summary
Orval generates TypeScript client code from OpenAPI specifications, and it copies certain vendor-extension fields — specifically x-enumDescriptions and x-enumNames — directly into generated source as comments/string literals without escaping. By crafting an enum description that breaks out of the generated comment/object-literal context, an attacker who controls an OpenAPI spec consumed by Orval can inject arbitrary JavaScript into the generated client file. When that generated file is subsequently imported or executed (e.g. during a build or test run), the injected code executes with the privileges of the developer or CI pipeline running it. The PoC demonstrates this by embedding a child_process.execSync('id') payload inside an enum description that is emitted verbatim into the generated model file.
Vulnerability Details
Root Cause
Orval interpolates x-enumDescriptions / x-enumNames values from the input OpenAPI spec into generated TypeScript source without escaping special characters (comment terminators, braces, quotes), allowing spec content to break out of its intended syntactic context and inject executable code.
Attack Vector
- Craft an OpenAPI spec whose schema includes an
x-enumDescriptionsentry containing a string that closes the generated block comment/object literal early (e.g.*/ }; (function(){ ... })(); export const Dummy = { /*). - Get the victim to run
npx orvalagainst this spec (e.g. via a shared/public API spec, a dependency, or a CI pipeline that regenerates clients from a remote spec URL). - Orval writes the injected code verbatim into the generated model file (e.g.
generated/model/testEnum.ts). - When any code imports the generated module (directly, via a build step, or via test execution), the injected
child_process.execSyncpayload runs, demonstrated by printing the output ofid.
Impact
Arbitrary code execution on the machine (developer workstation or CI runner) that generates or imports the poisoned client code, via nothing more than an untrusted OpenAPI specification — a supply-chain-style attack against the code-generation pipeline.
Environment / Lab Setup
Target: orval@7.10.0 (Node.js v20/v22, npm)
Attacker: ability to supply/host an OpenAPI spec that the victim runs through `npx orval`
Proof of Concept
PoC Script
See
orval.config.js,openapi.yaml, andexploit.tsin this folder.
| |
Running npx orval against the malicious openapi.yaml generates a TypeScript model file containing the injected execSync('id') call; running exploit.ts (which simply imports the generated model) triggers execution of that injected code, printing the current user/group IDs to prove arbitrary command execution.
Detection & Indicators of Compromise
grep -R "execSync\|require('child_process')" generated/
Signs of compromise:
- Generated TypeScript client files containing
require('child_process'),execSync, or other non-declarative statements outside the expected type/model definitions. - Unexpected process spawns or shell command execution immediately following a
npx orvalcodegen step in CI logs. - OpenAPI specs sourced from third parties/untrusted URLs containing unusually long or syntax-breaking
x-enumDescriptions/x-enumNamesvalues.
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade to Orval >= 8.0.2, which escapes these strings using js-string-escape |
| Interim mitigation | Treat all OpenAPI specs as untrusted input; review specs from external sources before running codegen, and avoid running orval against remote/unauthenticated spec URLs in CI without validation |
References
Notes
Mirrored from https://github.com/boroeurnprach/CVE-2026-23947-PoC on 2026-07-05. The upstream repository is README-only (a walkthrough); the orval.config.js, openapi.yaml, and exploit.ts files in this folder were reconstructed verbatim from the code blocks in that walkthrough to provide runnable PoC artifacts.
| |