Every CVE Search/ Get API key

CVE-2026-54662

swagger-typescript-api vulnerable to code injection via unescaped `servers[0].url` in fetch http-client template

8.3 HighFix available

swagger-typescript-api generates API clients for Fetch or Axios from OpenAPI specifications. Prior to 13.12.2, src/code-gen-process.ts createApiConfig copies servers[0].url into apiConfig.baseUrl, and templates/base/http-clients/fetch-http-client.ejs interpolates apiConfig.baseUrl into the generated HttpClient baseUrl field without escaping, allowing an attacker-controlled OpenAPI spec to inject TypeScript static field code that executes when the generated fetch client 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

0.35%Up 0.1 points since Jul 30, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.3

swagger-typescript-api vulnerable to code injection via unescaped `servers[0].url` in fetch http-client template

swagger-typescript-api generates API clients for Fetch or Axios from OpenAPI specifications. Prior to 13.12.2, src/code-gen-process.ts createApiConfig copies servers[0].url into apiConfig.baseUrl, and templates/base/http-clients/fetch-http-client.ejs interpolates apiConfig.baseUrl into the generated HttpClient baseUrl field without escaping, allowing an attacker-controlled OpenAPI spec to inject TypeScript static field code that executes when the generated fetch client module is imported. This issue is fixed in version 13.12.2.

Record
CVE-2026-54662
CVSS 3.1
8.3 HighCVSS: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-50363 8.3

swagger-typescript-api generates API clients for Fetch or Axios from OpenAPI specifications. Prior to 13.12.2, src/code-gen-process.ts createApiConfig copies servers[0].url into apiConfig.baseUrl, and templates/base/http-clients/fetch-http-client.ejs interpolates apiConfig.baseUrl into the generated HttpClient baseUrl field without escaping, allowing an attacker-controlled OpenAPI spec to inject TypeScript static field code that executes when the generated fetch client module is imported. This issue is fixed in version 13.12.2.

Record
EUVD-2026-50363
CVSS 3.1
8.3 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-hqj5-cw9f-rx67 8.3

swagger-typescript-api vulnerable to code injection via unescaped `servers[0].url` in fetch http-client template

Summary

swagger-typescript-api interpolates servers[0].url directly into a TypeScript class-body field initializer of the generated fetch HttpClient (templates/base/http-clients/fetch-http-client.ejs:75), without any escaping. A malicious URL containing a " closes the string literal that initializes public baseUrl and exposes the surrounding class body to injection. The most direct exploit declares a new static field whose initializer is an async IIFE — TypeScript evaluates static field initializers at class definition time, which is at module load. A consumer who imports the generated client (or anything that transitively imports it) executes the injected code with no further interaction — no instantiation, no method call, no use of the baseUrl. The attacker controls the OpenAPI spec; the victim is whoever runs the generator and imports the result.

This is the highest-impact sink in the package: the trigger requires only a bare import of the generated module.

Details

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

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

The fetch http-client template (templates/base/http-clients/fetch-http-client.ejs:75) then interpolates that value into a TS string literal that initializes a public class-body field of the generated HttpClient:

export class HttpClient<SecurityDataType = unknown> {
    public baseUrl: string = "<%~ apiConfig.baseUrl %>";
    private securityData: SecurityDataType | null = null;
    ...
}

<%~ %> 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.

TypeScript class-body grammar permits any number of field declarations and static blocks between { and }. A spec value of the form:

URL"; static _pwn = (IIFE)(); public x: string = "

produces the following class body:

export class HttpClient<SecurityDataType = unknown> {
  public baseUrl: string = "URL";
  static _pwn = (IIFE)();    // <-- static field initializer
  public x: string = "";
  private securityData: SecurityDataType | null = null;
  ...
}

The static _pwn = (IIFE)() declaration's initializer is evaluated at class definition — i.e. when the TS class declaration is processed, which is at the moment the generated module is imported. The trailing public x: string = " reopens a string that the template's own closing " terminates, keeping the file syntactically valid TypeScript.

The same Api class (in default/api.ejs) extends HttpClient. Importing the generated module evaluates the HttpClient class declaration during module initialization — no new HttpClient(), no new Api(), no method call. Importing anything that transitively depends on the generated module is sufficient.

PoC

Self-contained reproducer (run.sh runs end-to-end: install pinned package → generate from control + payload → bundle with esbuild → bare-import → check canary). Tested on [email protected] and Node v24.11.1.

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

https://api.example.com"; static _pwn = (async () => { try { const fs = await import('node:fs'); const data = fs.readFileSync('/etc/passwd', 'utf8'); fs.writeFileSync('/tmp/sta_canary', data); } catch (e) {} })(); public x: string = "

Minimal payload spec:

{
  "openapi": "3.0.0",
  "info": { "title": "FetchPayloadAPI", "version": "1.0.0" },
  "servers": [
    {
      "url": "https://api.example.com\"; static _pwn = (async () => { try { const fs = await import('node:fs'); const data = fs.readFileSync('/etc/passwd', 'utf8'); fs.writeFileSync('/tmp/sta_canary', data); } catch (e) {} })(); public x: string = \""
    }…
Record
GHSA-hqj5-cw9f-rx67
CVSS 3.1
8.3 HighCVSS: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 OpenAPI specifications. Prior to 13.12.2, src/code-gen-process.ts createApiConfig copies servers[0].url into apiConfig.baseUrl, and templates/base/http-clients/fetch-http-client.ejs interpolates apiConfig.baseUrl into the generated HttpClient baseUrl field without escaping, allowing an attacker-controlled OpenAPI spec to inject TypeScript static field code that executes when the generated fetch client module is imported. This issue is fixed in version 13.12.2.

Record
CVE-2026-54662
CVSS 3.1
8.3 HighCVSS: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 `servers[0].url` in fetch http-client template

swagger-typescript-api generates API clients for Fetch or Axios from OpenAPI specifications. Prior to 13.12.2, src/code-gen-process.ts createApiConfig copies servers[0].url into apiConfig.baseUrl, and templates/base/http-clients/fetch-http-client.ejs interpolates apiConfig.baseUrl into the generated HttpClient baseUrl field without escaping, allowing an attacker-controlled OpenAPI spec to inject TypeScript static field code that executes when the generated fetch client module is imported. This issue is fixed in version 13.12.2.

Record
CVE-2026-54662
CVSS 3.1
8.3 HighCVSS: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-hqj5-cw9f-rx67 8.3

swagger-typescript-api vulnerable to code injection via unescaped `servers[0].url` in fetch http-client template

Summary

swagger-typescript-api interpolates servers[0].url directly into a TypeScript class-body field initializer of the generated fetch HttpClient (templates/base/http-clients/fetch-http-client.ejs:75), without any escaping. A malicious URL containing a " closes the string literal that initializes public baseUrl and exposes the surrounding class body to injection. The most direct exploit declares a new static field whose initializer is an async IIFE — TypeScript evaluates static field initializers at class definition time, which is at module load. A consumer who imports the generated client (or anything that transitively imports it) executes the injected code with no further interaction — no instantiation, no method call, no use of the baseUrl. The attacker controls the OpenAPI spec; the victim is whoever runs the generator and imports the result.

This is the highest-impact sink in the package: the trigger requires only a bare import of the generated module.

Details

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

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

The fetch http-client template (templates/base/http-clients/fetch-http-client.ejs:75) then interpolates that value into a TS string literal that initializes a public class-body field of the generated HttpClient:

export class HttpClient<SecurityDataType = unknown> {
    public baseUrl: string = "<%~ apiConfig.baseUrl %>";
    private securityData: SecurityDataType | null = null;
    ...
}

<%~ %> 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.

TypeScript class-body grammar permits any number of field declarations and static blocks between { and }. A spec value of the form:

URL"; static _pwn = (IIFE)(); public x: string = "

produces the following class body:

export class HttpClient<SecurityDataType = unknown> {
  public baseUrl: string = "URL";
  static _pwn = (IIFE)();    // <-- static field initializer
  public x: string = "";
  private securityData: SecurityDataType | null = null;
  ...
}

The static _pwn = (IIFE)() declaration's initializer is evaluated at class definition — i.e. when the TS class declaration is processed, which is at the moment the generated module is imported. The trailing public x: string = " reopens a string that the template's own closing " terminates, keeping the file syntactically valid TypeScript.

The same Api class (in default/api.ejs) extends HttpClient. Importing the generated module evaluates the HttpClient class declaration during module initialization — no new HttpClient(), no new Api(), no method call. Importing anything that transitively depends on the generated module is sufficient.

PoC

Self-contained reproducer (run.sh runs end-to-end: install pinned package → generate from control + payload → bundle with esbuild → bare-import → check canary). Tested on [email protected] and Node v24.11.1.

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

https://api.example.com"; static _pwn = (async () => { try { const fs = await import('node:fs'); const data = fs.readFileSync('/etc/passwd', 'utf8'); fs.writeFileSync('/tmp/sta_canary', data); } catch (e) {} })(); public x: string = "

Minimal payload spec:

{
  "openapi": "3.0.0",
  "info": { "title": "FetchPayloadAPI", "version": "1.0.0" },
  "servers": [
    {
      "url": "https://api.example.com\"; static _pwn = (async () => { try { const fs = await import('node:fs'); const data = fs.readFileSync('/etc/passwd', 'utf8'); fs.writeFileSync('/tmp/sta_canary', data); } catch (e) {} })(); public x: string = \""
    }…
Record
GHSA-hqj5-cw9f-rx67
CVSS 3.1
8.3 HighCVSS: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

Affected packages
PackageAffectedFixed
swagger-typescript-api
npm
through 13.12.1
13.12.2
swagger-typescript-api
npm
before 13.12.2
13.12.2

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-54662 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.35%, the 28th percentile. Fixed in swagger-typescript-api 13.12.2.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open