diff --git a/advisories/unreviewed/2025/10/GHSA-q2pj-6v73-8rgj/GHSA-q2pj-6v73-8rgj.json b/advisories/unreviewed/2025/10/GHSA-q2pj-6v73-8rgj/GHSA-q2pj-6v73-8rgj.json index 614019185e6f0..d9b551c30cf37 100644 --- a/advisories/unreviewed/2025/10/GHSA-q2pj-6v73-8rgj/GHSA-q2pj-6v73-8rgj.json +++ b/advisories/unreviewed/2025/10/GHSA-q2pj-6v73-8rgj/GHSA-q2pj-6v73-8rgj.json @@ -1,14 +1,43 @@ { "schema_version": "1.4.0", "id": "GHSA-q2pj-6v73-8rgj", - "modified": "2025-10-29T18:30:33Z", + "modified": "2025-10-29T18:30:40Z", "published": "2025-10-29T18:30:33Z", "aliases": [ "CVE-2025-60542" ], - "details": "SQL Injection vulnerability in TypeORM before 0.3.26 via crafted request to repository.save or repository.update due to the sqlstring call using stringifyObjects default to false.", - "severity": [], - "affected": [], + "summary": "SQL Inection on TypeORM+MySQL Configuration on typeorm <= 0.3.25", + "details": "### Summary\n\nSQL Injection vulnerability in TypeORM before 0.3.26 via crafted request to repository.save or repository.update due to the sqlstring call using stringifyObjects default to false.\n\n### Details\n\nVulnerable Code:\n\n```\nconst { username, city, name} = req.body;\nconst updateData = {\n username,\n city,\n name,\n id:userId\n }; // Developer aims to only allow above three fields to be updated \nconst result = await userRepo.save(updateData);\n```\n\nIntended Payload (non-malicious):\n\n\n`\nusername=myusername&city=Riga&name=Javad\n`\n\n_OR_\n\n`{username:\"myusername\",phone:12345,name:\"Javad\"}\n`\n\nSQL query produced:\n\n```\nUPDATE `user` \nSET `username` = 'myusername', \n `city` = 'Riga', \n `name` = 'Javad' \nWHERE `id` IN (1);\n\n```\n\nMalicious Payload:\n\n`username=myusername&city[name]=Riga&city[role]=admin\n`\n_OR_\n\n`{username:\"myusername\",city:{name:\"Javad\",role:\"admin\"}}\n`\n\nSQL query produced with Injected Column:\n\n```\nUPDATE `user` \nSET `username` = 'myusername', \n `city` = `name` = 'Javad', \n `role` = 'admin' \nWHERE `id` IN (1);\n\n```\n_Above query is valid as `city` = `name` = ‘Javad’ is a boolean expression resulting in `city` = 1 (false). “role” column is injected and updated._\n\nUnderlying issue was due to TypeORM using mysql2 [without specifying a value for the stringifyObjects option](https://github.com/typeorm/typeorm/blob/0.3.25/src/driver/mysql/MysqlConnectionOptions.ts). In both mysql and mysql2 this [option defaults to false](https://github.com/sidorares/node-mysql2/blob/e359f454a76ba5dc31b91adf7bdb4099ca317bb5/lib/connection_config.js#L124). This option is then passed into [SQLString library as false](https://github.com/sidorares/node-mysql2/blob/e359f454a76ba5dc31b91adf7bdb4099ca317bb5/lib/base/connection.js#L524). This results in sqlstring [parsing objects in a strange way using objectToValues.](https://github.com/mysqljs/sqlstring/blob/cd528556b4b6bcf300c3db515026935dedf7cfa1/lib/SqlString.js#L54)", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L/SC:L/SI:H/SA:L" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "typeorm" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "0.3.26" + } + ] + } + ], + "database_specific": { + "last_known_affected_version_range": "<= 0.3.25" + } + } + ], "references": [ { "type": "ADVISORY", @@ -32,8 +61,10 @@ } ], "database_specific": { - "cwe_ids": [], - "severity": null, + "cwe_ids": [ + "CWE-89" + ], + "severity": "CRITICAL", "github_reviewed": false, "github_reviewed_at": null, "nvd_published_at": "2025-10-29T16:15:34Z"