Skip to content

Commit

Permalink
fix(endpoints/fs/readDir): don't read symlinks that are not allowed b… (
Browse files Browse the repository at this point in the history
  • Loading branch information
amrbashir authored Sep 8, 2022
1 parent 5b0b8ef commit f4121c1
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changes/fix-readir-symlink-scope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri": patch
---

Fix `fs.readDir` recursive option reading symlinked directories that are not allowed by the scope.
45 changes: 39 additions & 6 deletions core/tauri/src/api/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use serde::Serialize;
use std::{
fs::{self, metadata},
fs::{self, metadata, symlink_metadata},
path::{Path, PathBuf},
};
use tempfile::{self, tempdir};
Expand All @@ -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();
Expand All @@ -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
},
Expand Down
1 change: 1 addition & 0 deletions core/tauri/src/api/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
12 changes: 9 additions & 3 deletions core/tauri/src/endpoints/file_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down

0 comments on commit f4121c1

Please sign in to comment.