The readDir Endpoint Scope can be Bypassed With Symbolic Links in Tauri
Description
Tauri is a framework for building binaries for all major desktop platforms. Due to missing canonicalization when readDir is called recursively, it was possible to display directory listings outside of the defined fs scope. This required a crafted symbolic link or junction folder inside an allowed path of the fs scope. No arbitrary file content could be leaked. The issue has been resolved in version 1.0.6 and the implementation now properly checks if the requested (sub) directory is a symbolic link outside of the defined scope. Users are advised to upgrade. Users unable to upgrade should disable the readDir endpoint in the allowlist inside the tauri.conf.json.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Tauri v1.0.5 and earlier allow directory listing outside the fs scope via crafted symlinks due to missing canonicalization in readDir.
Root
Cause
The Tauri framework's readDir API endpoint, when called with the recursive option, did not perform proper canonicalization of path components. This allowed directory listings to escape the user-configured filesystem scope if an attacker could place a symbolic link or junction folder inside an otherwise authorized directory [1].
Exploitation
Prerequisites
An attacker must first gain the ability to write a symbolic link or directory junction within a path that is explicitly allowed by the application's fs scope configuration. No authentication bypass is required beyond that file-write capability. The exploit is triggered when the application calls readDir recursively on the parent directory, causing the resolver to follow the symlink outside the sanctioned path [2].
Impact
A successful attack enables an attacker to enumerate files and folders outside the intended scope, potentially revealing sensitive information about the file system layout and filenames. Crucially, no arbitrary file *content* can be read or exfiltrated — only directory listings are disclosed [1].
Mitigation
The issue is fixed in Tauri v1.0.6, where the implementation now checks whether a (sub)directory is a symbolic link pointing outside the defined scope before recursing into it [2][3]. Users unable to upgrade can disable the readDir endpoint in the allowlist section of tauri.conf.json as a workaround [1].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
tauricrates.io | < 1.0.6 | 1.0.6 |
Affected products
2- tauri-apps/tauriv5Range: < 1.0.6
Patches
1bb178829086efix(endpoints/fs/readDir): don't read symlinks that are not allowed b… (#5123)
4 files changed · +54 −9
.changes/fix-readir-symlink-scope.md+5 −0 added@@ -0,0 +1,5 @@ +--- +"tauri": patch +--- + +Fix `fs.readDir` recursive option reading symlinked directories that are not allowed by the scope.
core/tauri/src/api/dir.rs+39 −6 modified@@ -6,7 +6,7 @@ use serde::Serialize; use std::{ - fs::{self, metadata}, + fs::{self, metadata, symlink_metadata}, path::{Path, PathBuf}, }; use tempfile::{self, tempdir}; @@ -31,8 +31,36 @@ pub fn is_dir<P: AsRef<Path>>(path: P) -> crate::api::Result<bool> { metadata(path).map(|md| md.is_dir()).map_err(Into::into) } +fn is_symlink<P: AsRef<Path>>(path: P) -> crate::api::Result<bool> { + // TODO: remove the different implementation once we raise tauri's MSRV to at least 1.58 + #[cfg(windows)] + let ret = symlink_metadata(path) + .map(|md| md.is_symlink()) + .map_err(Into::into); + + #[cfg(not(windows))] + let ret = symlink_metadata(path) + .map(|md| md.file_type().is_symlink()) + .map_err(Into::into); + + ret +} + /// Reads a directory. Can perform recursive operations. pub fn read_dir<P: AsRef<Path>>(path: P, recursive: bool) -> crate::api::Result<Vec<DiskEntry>> { + read_dir_with_options(path, recursive, ReadDirOptions { scope: None }) +} + +#[derive(Clone, Copy)] +pub(crate) struct ReadDirOptions<'a> { + pub scope: Option<&'a crate::FsScope>, +} + +pub(crate) fn read_dir_with_options<P: AsRef<Path>>( + path: P, + recursive: bool, + options: ReadDirOptions<'_>, +) -> crate::api::Result<Vec<DiskEntry>> { let mut files_and_dirs: Vec<DiskEntry> = vec![]; for entry in fs::read_dir(path)? { let path = entry?.path(); @@ -42,11 +70,16 @@ pub fn read_dir<P: AsRef<Path>>(path: P, recursive: bool) -> crate::api::Result< files_and_dirs.push(DiskEntry { path: path.clone(), children: if flag { - Some(if recursive { - read_dir(&path_as_string, true)? - } else { - vec![] - }) + Some( + if recursive + && (!is_symlink(&path_as_string)? + || options.scope.map(|s| s.is_allowed(&path)).unwrap_or(true)) + { + read_dir_with_options(&path_as_string, true, options)? + } else { + vec![] + }, + ) } else { None },
core/tauri/src/api/file.rs+1 −0 modified@@ -74,6 +74,7 @@ pub fn read_binary<P: AsRef<Path>>(file: P) -> crate::api::Result<Vec<u8>> { #[cfg(test)] mod test { use super::*; + #[cfg(not(windows))] use crate::api::Error; use quickcheck::{Arbitrary, Gen};
core/tauri/src/endpoints/file_system.rs+9 −3 modified@@ -191,9 +191,15 @@ impl Cmd { path, dir, )?; - dir::read_dir(&resolved_path, recursive) - .with_context(|| format!("path: {}", resolved_path.display())) - .map_err(Into::into) + dir::read_dir_with_options( + &resolved_path, + recursive, + dir::ReadDirOptions { + scope: Some(&context.window.state::<Scopes>().fs), + }, + ) + .with_context(|| format!("path: {}", resolved_path.display())) + .map_err(Into::into) } #[module_command_handler(fs_copy_file)]
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-28m8-9j7v-x499ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-39215ghsaADVISORY
- github.com/tauri-apps/tauri/commit/bb178829086e80916f9be190f02d83bc25802799ghsaWEB
- github.com/tauri-apps/tauri/issues/4882ghsax_refsource_MISCWEB
- github.com/tauri-apps/tauri/pull/5123ghsax_refsource_MISCWEB
- github.com/tauri-apps/tauri/pull/5123/commits/1f9b9e8d26a2c915390323e161020bcb36d44678ghsax_refsource_MISCWEB
- github.com/tauri-apps/tauri/releases/tag/tauri-v1.0.6ghsaWEB
- github.com/tauri-apps/tauri/security/advisories/GHSA-28m8-9j7v-x499ghsax_refsource_CONFIRMWEB
- rustsec.org/advisories/RUSTSEC-2022-0088.htmlghsaWEB
News mentions
0No linked articles in our index yet.