PoC Archive PoC Archive
High CVE-2026-23947 patched

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

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-01
Author / ResearcherBoroeurn Prach
CVE / AdvisoryCVE-2026-23947
Categorymisc
SeverityHigh
CVSS ScoreNot specified in source
StatusPoC
Tagsorval, openapi, code-generation, arbitrary-code-execution, nodejs, supply-chain, typescript, build-tooling
RelatedN/A

Affected Target

FieldValue
Software / SystemOrval (OpenAPI-to-TypeScript client generator), version 7.10.0
Versions AffectedOrval < 8.0.2 (fixed in 8.0.2)
Language / PlatformNode.js / TypeScript build tooling
Authentication RequiredNo (requires the victim to run Orval against an attacker-controlled/untrusted OpenAPI spec)
Network Access RequiredNo (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

  1. Craft an OpenAPI spec whose schema includes an x-enumDescriptions entry containing a string that closes the generated block comment/object literal early (e.g. */ }; (function(){ ... })(); export const Dummy = { /*).
  2. Get the victim to run npx orval against this spec (e.g. via a shared/public API spec, a dependency, or a CI pipeline that regenerates clients from a remote spec URL).
  3. Orval writes the injected code verbatim into the generated model file (e.g. generated/model/testEnum.ts).
  4. When any code imports the generated module (directly, via a build step, or via test execution), the injected child_process.execSync payload runs, demonstrated by printing the output of id.

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, and exploit.ts in this folder.

1
2
3
4
5
6
mkdir orval-poc && cd orval-poc
npm init -y
npm install orval@7.10.0 axios
npm install -D tsx
npx orval
npx tsx exploit.ts

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 orval codegen step in CI logs.
  • OpenAPI specs sourced from third parties/untrusted URLs containing unusually long or syntax-breaking x-enumDescriptions/x-enumNames values.

Remediation

ActionDetail
Primary fixUpgrade to Orval >= 8.0.2, which escapes these strings using js-string-escape
Interim mitigationTreat 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.

orval.config.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
module.exports = {
  test: {
    input: './openapi.yaml',
    output: {
      target: './generated/api.ts',
      schemas: './generated/model',
      mode: 'split',
    },
  },
};