Miggo Logo

CVE-2025-61786: Deno's --deny-read check does not prevent permission bypass

3.3

CVSS Score
3.1

Basic Information

EPSS Score
0.01025%
Published
10/8/2025
Updated
10/8/2025
KEV Status
No
Technology
TechnologyRust

Technical Details

CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Package NameEcosystemVulnerable VersionsFirst Patched Version
denorust< 2.5.32.5.3

Vulnerability Intelligence
Miggo AIMiggo AI

Miggo AIRoot Cause Analysis

The vulnerability allows bypassing Deno's read permission checks. The PoC demonstrates that when a script is run with --deny-read, it's still possible to get file metadata using file.stat() and file.statSync() on a file handle that was opened with only write permissions.

The root cause is in the underlying native Rust functions (ops) that implement the JavaScript API. The functions op_fs_file_stat_sync and op_fs_file_stat_async in ext/fs/ops.rs were responsible for getting the file statistics. However, as shown in the patch, the original implementations of these functions did not perform any permission checks. They would directly retrieve the file stats for the given file resource ID.

The fix, seen in commit 1ab2268c0bcbf9b0468e0e36963f77f8c31c73ec, introduces a permission check within both functions. It now retrieves the file path associated with the resource and calls check_open with a Read access kind. If the script does not have read permissions for that path, the operation will fail, thus closing the security hole.

Therefore, the vulnerable functions are the original versions of op_fs_file_stat_sync and op_fs_file_stat_async before the security patch was applied. These are the functions that would appear in a runtime profile when the vulnerable Deno.FsFile.prototype.stat or Deno.FsFile.prototype.statSync methods are called.

Vulnerable functions

op_fs_file_stat_sync
ext/fs/ops.rs
This function is the backing implementation for `Deno.FsFile.prototype.statSync`. The vulnerability lies in the fact that this function directly calls `file.stat_sync()` without first checking for read permissions. The patch adds a call to `state.borrow::<P>().check_open()` to enforce the read permission check before accessing file stats, thus mitigating the permission bypass.
op_fs_file_stat_async
ext/fs/ops.rs
This function is the backing implementation for `Deno.FsFile.prototype.stat`. The vulnerability lies in the fact that this function directly calls `file.stat_async()` without first checking for read permissions. The patch adds a call to `state.borrow().borrow::<P>().check_open()` to enforce the read permission check before accessing file stats, thus mitigating the permission bypass.

WAF Protection Rules

WAF Rule

### Summ*ry `**no.*s*il*.prototyp*.st*t` *n* `**no.*s*il*.prototyp*.st*tSyn*` *r* not limit** *y t** p*rmission mo**l ****k `--**ny-r***=./`. It's possi*l* to r*tri*v* st*ts *rom *il*s t**t t** us*r *o not **v* *xpli*it r*** ****ss to (t** s*ript

Reasoning

T** vuln*r**ility *llows *yp*ssin* **no's r*** p*rmission ****ks. T** Po* **monstr*t*s t**t w**n * s*ript is run wit* `--**ny-r***`, it's still possi*l* to **t *il* m*t***t* usin* `*il*.st*t()` *n* `*il*.st*tSyn*()` on * *il* **n*l* t**t w*s op*n** w