CVE-2026-54664
swagger-typescript-api vulnerable to code injection via unescaped enum string values
swagger-typescript-api generates API clients for Fetch or Axios from an OpenAPI Specification. Prior to 13.12.2, src/schema-parser/base-schema-parsers/enum.ts passes components.schemas.*.enum[i] values to Ts.StringValue in src/configuration.ts without escaping before templates/base/enum-data-contract.ejs renders TypeScript enum declarations, allowing an attacker-controlled OpenAPI spec to inject code that executes when the generated module is imported. This issue is fixed in version 13.12.2.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
8.3
swagger-typescript-api vulnerable to code injection via unescaped enum string values
swagger-typescript-api generates API clients for Fetch or Axios from an OpenAPI Specification. Prior to 13.12.2, src/schema-parser/base-schema-parsers/enum.ts passes components.schemas.*.enum[i] values to Ts.StringValue in src/configuration.ts without escaping before templates/base/enum-data-contract.ejs renders TypeScript enum declarations, allowing an attacker-controlled OpenAPI spec to inject code that executes when the generated module is imported. This issue is fixed in version 13.12.2.
- Record
CVE-2026-54664- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H - Weakness
- CWE-74, CWE-94, CWE-1336
- Updated
- 2026-11-02
EUVDEUVD-2026-50366
8.3
swagger-typescript-api generates API clients for Fetch or Axios from an OpenAPI Specification. Prior to 13.12.2, src/schema-parser/base-schema-parsers/enum.ts passes components.schemas.*.enum[i] values to Ts.StringValue in src/configuration.ts without escaping before templates/base/enum-data-contract.ejs renders TypeScript enum declarations, allowing an attacker-controlled OpenAPI spec to inject code that executes when the generated module is imported. This issue is fixed in version 13.12.2.
- Record
EUVD-2026-50366- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-5f94-x226-ccpm
8.3
swagger-typescript-api vulnerable to code injection via unescaped enum string values
Summary
swagger-typescript-api interpolates components.schemas.*.enum[i] string values into the body of generated TypeScript enum declarations without escaping. A malicious enum value can close the enclosing string literal, terminate the enum body, and inject a bare-block IIFE that executes at module load the first time the generated client is imported. The trigger requires no instantiation and no method call — only an import of the generated module. The attacker controls the OpenAPI spec (remote --url, third-party / public spec, multi-tenant platform); the victim is whoever runs the generator and imports the result (the developer, their CI runner, or any downstream consumer of the generated package). Impact is arbitrary code execution with the importing process's privileges — read any file the importer can read, write any file, exfiltrate secrets, etc.
Details
The root cause is Ts.StringValue in src/configuration.ts:250:
StringValue: (content: unknown) => `"${content}"`,
It wraps a value in double quotes with zero escaping — no handling of ", \, newlines, or anything else. The codebase's only escape function (escapeJSDocContent in src/schema-parser/schema-formatters.ts:127) only replaces */ and is never applied to this path.
Enum string values reach Ts.StringValue at src/schema-parser/base-schema-parsers/enum.ts:100 and :116:
return this.config.Ts.StringValue(value);
// ...
value: this.config.Ts.StringValue(enumName),
The result is interpolated raw into the enum body in templates/base/enum-data-contract.ejs (default enumStyle: "enum" branch, lines 24-31):
export enum <%~ name %> {
<%~ _.map($content, ({ key, value, description }) => {
...
return [
formattedDescription && `/** ${formattedDescription} */`,
`${key} = ${value}`
].filter(Boolean).join("\n");
}).join(",\n") %>
}
Where ${value} is the result of Ts.StringValue — raw "${content}". An attacker-controlled enum value containing a " closes the string and exposes the surrounding code position to injection.
A ;} sequence terminates the enum body mid-stream. A { opens a bare block at module top level. An async IIFE inside that block runs at module load. A trailing // consumes the closing " that Ts.StringValue still appends, and the template's own closing } of the enum becomes the closing } of the bare block. Resulting TypeScript parses cleanly, bundles cleanly through esbuild, and the IIFE fires on bare await import('./generated.js').
The same Ts.StringValue function is also called from src/schema-parser/schema-utils.ts:215,406, src/schema-parser/base-schema-parsers/object.ts:47, and src/schema-parser/base-schema-parsers/discriminator.ts:88,121,131,195. Those other call sites currently land in type-level positions (interface/type bodies) where the breakout cannot reach runtime — they are safe by accident of context, not by escaping. A fix that hardens Ts.StringValue itself protects those sites too as defense in depth.
PoC
Self-contained reproducer (run.sh runs end-to-end: install pinned package → generate from control + payload → bundle with esbuild → bare-import → check canary) is added in the comments. Tested on [email protected] and Node v24.11.1.
Malicious enum value (literal string, JSON-encoded in the spec below):
blue";}<NEWLINE>{(async()=>{ try { const fs=await import('node:fs'); const d=fs.readFileSync('/etc/passwd','utf8'); fs.writeFileSync('/tmp/sta_canary',d); } catch(e){} })();//
Minimal payload spec:
{
"openapi": "3.0.0",
"info": { "title": "EnumPayloadAPI", "version": "1.0.0" },
"components": {
"schemas": {
"Color": {
"type": "string",
"enum": [
"red",
"blue\";}\n{(async()=>{try{const fs=await import('node:fs');const…
- Record
GHSA-5f94-x226-ccpm- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H - Weakness
- CWE-74, CWE-94, CWE-1336
- Updated
- 2026-11-02
NVD
8.3
swagger-typescript-api generates API clients for Fetch or Axios from an OpenAPI Specification. Prior to 13.12.2, src/schema-parser/base-schema-parsers/enum.ts passes components.schemas.*.enum[i] values to Ts.StringValue in src/configuration.ts without escaping before templates/base/enum-data-contract.ejs renders TypeScript enum declarations, allowing an attacker-controlled OpenAPI spec to inject code that executes when the generated module is imported. This issue is fixed in version 13.12.2.
- Record
CVE-2026-54664- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H - Weakness
- CWE-74, CWE-94, CWE-1336
- Updated
- 2026-11-02
OSV
8.3
swagger-typescript-api vulnerable to code injection via unescaped enum string values
swagger-typescript-api generates API clients for Fetch or Axios from an OpenAPI Specification. Prior to 13.12.2, src/schema-parser/base-schema-parsers/enum.ts passes components.schemas.*.enum[i] values to Ts.StringValue in src/configuration.ts without escaping before templates/base/enum-data-contract.ejs renders TypeScript enum declarations, allowing an attacker-controlled OpenAPI spec to inject code that executes when the generated module is imported. This issue is fixed in version 13.12.2.
- Record
CVE-2026-54664- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H - Weakness
- CWE-1336, CWE-74, CWE-94
- Updated
- 2026-11-02
OSVGHSA-5f94-x226-ccpm
8.3
swagger-typescript-api vulnerable to code injection via unescaped enum string values
Summary
swagger-typescript-api interpolates components.schemas.*.enum[i] string values into the body of generated TypeScript enum declarations without escaping. A malicious enum value can close the enclosing string literal, terminate the enum body, and inject a bare-block IIFE that executes at module load the first time the generated client is imported. The trigger requires no instantiation and no method call — only an import of the generated module. The attacker controls the OpenAPI spec (remote --url, third-party / public spec, multi-tenant platform); the victim is whoever runs the generator and imports the result (the developer, their CI runner, or any downstream consumer of the generated package). Impact is arbitrary code execution with the importing process's privileges — read any file the importer can read, write any file, exfiltrate secrets, etc.
Details
The root cause is Ts.StringValue in src/configuration.ts:250:
StringValue: (content: unknown) => `"${content}"`,
It wraps a value in double quotes with zero escaping — no handling of ", \, newlines, or anything else. The codebase's only escape function (escapeJSDocContent in src/schema-parser/schema-formatters.ts:127) only replaces */ and is never applied to this path.
Enum string values reach Ts.StringValue at src/schema-parser/base-schema-parsers/enum.ts:100 and :116:
return this.config.Ts.StringValue(value);
// ...
value: this.config.Ts.StringValue(enumName),
The result is interpolated raw into the enum body in templates/base/enum-data-contract.ejs (default enumStyle: "enum" branch, lines 24-31):
export enum <%~ name %> {
<%~ _.map($content, ({ key, value, description }) => {
...
return [
formattedDescription && `/** ${formattedDescription} */`,
`${key} = ${value}`
].filter(Boolean).join("\n");
}).join(",\n") %>
}
Where ${value} is the result of Ts.StringValue — raw "${content}". An attacker-controlled enum value containing a " closes the string and exposes the surrounding code position to injection.
A ;} sequence terminates the enum body mid-stream. A { opens a bare block at module top level. An async IIFE inside that block runs at module load. A trailing // consumes the closing " that Ts.StringValue still appends, and the template's own closing } of the enum becomes the closing } of the bare block. Resulting TypeScript parses cleanly, bundles cleanly through esbuild, and the IIFE fires on bare await import('./generated.js').
The same Ts.StringValue function is also called from src/schema-parser/schema-utils.ts:215,406, src/schema-parser/base-schema-parsers/object.ts:47, and src/schema-parser/base-schema-parsers/discriminator.ts:88,121,131,195. Those other call sites currently land in type-level positions (interface/type bodies) where the breakout cannot reach runtime — they are safe by accident of context, not by escaping. A fix that hardens Ts.StringValue itself protects those sites too as defense in depth.
PoC
Self-contained reproducer (run.sh runs end-to-end: install pinned package → generate from control + payload → bundle with esbuild → bare-import → check canary) is added in the comments. Tested on [email protected] and Node v24.11.1.
Malicious enum value (literal string, JSON-encoded in the spec below):
blue";}<NEWLINE>{(async()=>{ try { const fs=await import('node:fs'); const d=fs.readFileSync('/etc/passwd','utf8'); fs.writeFileSync('/tmp/sta_canary',d); } catch(e){} })();//
Minimal payload spec:
{
"openapi": "3.0.0",
"info": { "title": "EnumPayloadAPI", "version": "1.0.0" },
"components": {
"schemas": {
"Color": {
"type": "string",
"enum": [
"red",
"blue\";}\n{(async()=>{try{const fs=await import('node:fs');const…
- Record
GHSA-5f94-x226-ccpm- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H - Weakness
- CWE-1336, CWE-74, CWE-94
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
swagger-typescript-apinpm |
through 13.12.1 | 13.12.2 |
swagger-typescript-apinpm |
before 13.12.2 | 13.12.2 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-54664 is a high vulnerability (CVSS 8.3) in Acacode Swagger-typescript-api, published July 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.48%, the 41st percentile. Fixed in swagger-typescript-api 13.12.2.
References
github.com/acacode/swagger-typescript-api/security/advisories/GHSA-5f94-x226-ccpm
github.com/acacode/swagger-typescript-api/pull/1779
github.com/acacode/swagger-typescript-api/commit/306d59acb8ffbb00f953f807b97234b21f51d9de
github.com/acacode/swagger-typescript-api/releases/tag/v13.12.2
github.com/advisories/GHSA-5f94-x226-ccpm
github.com/CVEProject/cvelistV5/tree/main/cves/2026/54xxx/CVE-2026-54664.json
nvd.nist.gov/vuln/detail/CVE-2026-54664
github.com/acacode/swagger-typescript-api
Left out here: the rest of 2 source descriptions. The JSON record has them.