@@ -16,13 +16,13 @@ use std::{
16
16
borrow:: Cow ,
17
17
fs:: File ,
18
18
io:: { BufRead , BufReader , Read , Write } ,
19
- path:: PathBuf ,
19
+ path:: { Path , PathBuf } ,
20
20
str:: FromStr ,
21
21
sync:: Mutex ,
22
22
time:: { SystemTime , UNIX_EPOCH } ,
23
23
} ;
24
24
25
- use crate :: { scope:: Entry , Error , FsExt , SafeFilePath } ;
25
+ use crate :: { scope:: Entry , Error , SafeFilePath } ;
26
26
27
27
#[ derive( Debug , thiserror:: Error ) ]
28
28
pub enum CommandError {
@@ -942,6 +942,8 @@ pub fn resolve_file<R: Runtime>(
942
942
path : SafeFilePath ,
943
943
open_options : OpenOptions ,
944
944
) -> CommandResult < ( File , PathBuf ) > {
945
+ use crate :: FsExt ;
946
+
945
947
match path {
946
948
SafeFilePath :: Url ( url) => {
947
949
let path = url. as_str ( ) . into ( ) ;
@@ -974,40 +976,81 @@ pub fn resolve_path<R: Runtime>(
974
976
path
975
977
} ;
976
978
979
+ let fs_scope = webview. state :: < crate :: Scope > ( ) ;
980
+
977
981
let scope = tauri:: scope:: fs:: Scope :: new (
978
982
webview,
979
983
& FsScope :: Scope {
980
- allow : webview
981
- . fs_scope ( )
982
- . allowed
983
- . lock ( )
984
- . unwrap ( )
985
- . clone ( )
986
- . into_iter ( )
987
- . chain ( global_scope. allows ( ) . iter ( ) . filter_map ( |e| e. path . clone ( ) ) )
984
+ allow : global_scope
985
+ . allows ( )
986
+ . iter ( )
987
+ . filter_map ( |e| e. path . clone ( ) )
988
988
. chain ( command_scope. allows ( ) . iter ( ) . filter_map ( |e| e. path . clone ( ) ) )
989
989
. collect ( ) ,
990
- deny : webview
991
- . fs_scope ( )
992
- . denied
993
- . lock ( )
994
- . unwrap ( )
995
- . clone ( )
996
- . into_iter ( )
997
- . chain ( global_scope. denies ( ) . iter ( ) . filter_map ( |e| e. path . clone ( ) ) )
990
+ deny : global_scope
991
+ . denies ( )
992
+ . iter ( )
993
+ . filter_map ( |e| e. path . clone ( ) )
998
994
. chain ( command_scope. denies ( ) . iter ( ) . filter_map ( |e| e. path . clone ( ) ) )
999
995
. collect ( ) ,
1000
- require_literal_leading_dot : webview . fs_scope ( ) . require_literal_leading_dot ,
996
+ require_literal_leading_dot : fs_scope. require_literal_leading_dot ,
1001
997
} ,
1002
998
) ?;
1003
999
1004
- if scope. is_allowed ( & path) {
1000
+ let require_literal_leading_dot = fs_scope. require_literal_leading_dot . unwrap_or ( cfg ! ( unix) ) ;
1001
+
1002
+ if is_forbidden ( & fs_scope. scope , & path, require_literal_leading_dot)
1003
+ || is_forbidden ( & scope, & path, require_literal_leading_dot)
1004
+ {
1005
+ return Err ( CommandError :: Plugin ( Error :: PathForbidden ( path) ) ) ;
1006
+ }
1007
+
1008
+ if fs_scope. scope . is_allowed ( & path) || scope. is_allowed ( & path) {
1005
1009
Ok ( path)
1006
1010
} else {
1007
1011
Err ( CommandError :: Plugin ( Error :: PathForbidden ( path) ) )
1008
1012
}
1009
1013
}
1010
1014
1015
+ fn is_forbidden < P : AsRef < Path > > (
1016
+ scope : & tauri:: fs:: Scope ,
1017
+ path : P ,
1018
+ require_literal_leading_dot : bool ,
1019
+ ) -> bool {
1020
+ let path = path. as_ref ( ) ;
1021
+ let path = if path. is_symlink ( ) {
1022
+ match std:: fs:: read_link ( path) {
1023
+ Ok ( p) => p,
1024
+ Err ( _) => return false ,
1025
+ }
1026
+ } else {
1027
+ path. to_path_buf ( )
1028
+ } ;
1029
+ let path = if !path. exists ( ) {
1030
+ crate :: Result :: Ok ( path)
1031
+ } else {
1032
+ std:: fs:: canonicalize ( path) . map_err ( Into :: into)
1033
+ } ;
1034
+
1035
+ if let Ok ( path) = path {
1036
+ let path: PathBuf = path. components ( ) . collect ( ) ;
1037
+ scope. forbidden_patterns ( ) . iter ( ) . any ( |p| {
1038
+ p. matches_path_with (
1039
+ & path,
1040
+ glob:: MatchOptions {
1041
+ // this is needed so `/dir/*` doesn't match files within subdirectories such as `/dir/subdir/file.txt`
1042
+ // see: <https://github.com/tauri-apps/tauri/security/advisories/GHSA-6mv3-wm7j-h4w5>
1043
+ require_literal_separator : true ,
1044
+ require_literal_leading_dot,
1045
+ ..Default :: default ( )
1046
+ } ,
1047
+ )
1048
+ } )
1049
+ } else {
1050
+ false
1051
+ }
1052
+ }
1053
+
1011
1054
struct StdFileResource ( Mutex < File > ) ;
1012
1055
1013
1056
impl StdFileResource {
0 commit comments