Skip to content

Commit f323eb8

Browse files
committed
i am making it worse
1 parent caac44d commit f323eb8

File tree

6 files changed

+151
-119
lines changed

6 files changed

+151
-119
lines changed

plugins/fs/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ rustc-args = ["--cfg", "docsrs"]
1414
rustdoc-args = ["--cfg", "docsrs"]
1515

1616
[package.metadata.platforms.support]
17-
windows = { level = "full", notes = "No write access to `$RESOURCES` folder with MSI installer and NSIS installers in `perMachine` or `both` mode" }
17+
windows = { level = "full", notes = "Apps installed via MSI or NSIS in `perMachine` and `both` mode require admin permissions for write acces in `$RESOURCES` folder" }
1818
linux = { level = "full", notes = "No write access to `$RESOURCES` folder" }
1919
macos = { level = "full", notes = "No write access to `$RESOURCES` folder" }
2020
android = { level = "partial", notes = "Access is restricted to Application folder by default" }

plugins/fs/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77
path::{Path, PathBuf},
88
};
99

10-
#[path = "src/scope.rs"]
10+
#[path = "src/entryraw.rs"]
1111
#[allow(dead_code)]
1212
mod scope;
1313

plugins/fs/src/commands.rs

Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{
1616
borrow::Cow,
1717
fs::File,
1818
io::{BufReader, Lines, Read, Write},
19-
path::PathBuf,
19+
path::{Path, PathBuf},
2020
str::FromStr,
2121
sync::Mutex,
2222
time::{SystemTime, UNIX_EPOCH},
@@ -1002,37 +1002,88 @@ pub fn resolve_path<R: Runtime>(
10021002
let scope = tauri::scope::fs::Scope::new(
10031003
webview,
10041004
&FsScope::Scope {
1005-
allow: webview
1006-
.fs_scope()
1007-
.allowed
1008-
.lock()
1009-
.unwrap()
1010-
.clone()
1011-
.into_iter()
1012-
.chain(global_scope.allows().iter().filter_map(|e| e.path.clone()))
1005+
allow: global_scope
1006+
.allows()
1007+
.iter()
1008+
.filter_map(|e| e.path.clone())
10131009
.chain(command_scope.allows().iter().filter_map(|e| e.path.clone()))
10141010
.collect(),
1015-
deny: webview
1016-
.fs_scope()
1017-
.denied
1018-
.lock()
1019-
.unwrap()
1020-
.clone()
1021-
.into_iter()
1022-
.chain(global_scope.denies().iter().filter_map(|e| e.path.clone()))
1011+
deny: global_scope
1012+
.denies()
1013+
.iter()
1014+
.filter_map(|e| e.path.clone())
10231015
.chain(command_scope.denies().iter().filter_map(|e| e.path.clone()))
10241016
.collect(),
10251017
require_literal_leading_dot: webview.fs_scope().require_literal_leading_dot,
10261018
},
10271019
)?;
10281020

1029-
if scope.is_allowed(&path) {
1021+
let fs_scope = webview.fs_scope();
1022+
1023+
let require_literal_leading_dot = fs_scope.require_literal_leading_dot.unwrap_or(cfg!(unix));
1024+
1025+
if fs_scope
1026+
.scope
1027+
.as_ref()
1028+
.map(|s| is_forbidden(s, &path, require_literal_leading_dot))
1029+
.unwrap_or(false)
1030+
|| is_forbidden(&scope, &path, require_literal_leading_dot)
1031+
{
1032+
return Err(CommandError::Plugin(Error::PathForbidden(path)));
1033+
}
1034+
1035+
if fs_scope
1036+
.scope
1037+
.as_ref()
1038+
.map(|s| s.is_allowed(&path))
1039+
.unwrap_or(false)
1040+
|| scope.is_allowed(&path)
1041+
{
10301042
Ok(path)
10311043
} else {
10321044
Err(CommandError::Plugin(Error::PathForbidden(path)))
10331045
}
10341046
}
10351047

1048+
fn is_forbidden<P: AsRef<Path>>(
1049+
scope: &tauri::fs::Scope,
1050+
path: P,
1051+
require_literal_leading_dot: bool,
1052+
) -> bool {
1053+
let path = path.as_ref();
1054+
let path = if path.is_symlink() {
1055+
match std::fs::read_link(path) {
1056+
Ok(p) => p,
1057+
Err(_) => return false,
1058+
}
1059+
} else {
1060+
path.to_path_buf()
1061+
};
1062+
let path = if !path.exists() {
1063+
crate::Result::Ok(path)
1064+
} else {
1065+
std::fs::canonicalize(path).map_err(Into::into)
1066+
};
1067+
1068+
if let Ok(path) = path {
1069+
let path: PathBuf = path.components().collect();
1070+
scope.forbidden_patterns().iter().any(|p| {
1071+
p.matches_path_with(
1072+
&path,
1073+
glob::MatchOptions {
1074+
// this is needed so `/dir/*` doesn't match files within subdirectories such as `/dir/subdir/file.txt`
1075+
// see: <https://github.com/tauri-apps/tauri/security/advisories/GHSA-6mv3-wm7j-h4w5>
1076+
require_literal_separator: true,
1077+
require_literal_leading_dot,
1078+
..Default::default()
1079+
},
1080+
)
1081+
})
1082+
} else {
1083+
false
1084+
}
1085+
}
1086+
10361087
struct StdFileResource(Mutex<File>);
10371088

10381089
impl StdFileResource {

plugins/fs/src/entryraw.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
2+
// SPDX-License-Identifier: Apache-2.0
3+
// SPDX-License-Identifier: MIT
4+
5+
use std::path::PathBuf;
6+
7+
use serde::Deserialize;
8+
9+
#[derive(Deserialize)]
10+
#[serde(untagged)]
11+
pub(crate) enum EntryRaw {
12+
Value(PathBuf),
13+
Object { path: PathBuf },
14+
}

plugins/fs/src/lib.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ use serde::Deserialize;
1515
use tauri::{
1616
ipc::ScopeObject,
1717
plugin::{Builder as PluginBuilder, TauriPlugin},
18-
utils::acl::Value,
18+
utils::{acl::Value, config::FsScope},
1919
AppHandle, DragDropEvent, Manager, RunEvent, Runtime, WindowEvent,
2020
};
2121

2222
mod commands;
2323
mod config;
2424
#[cfg(not(target_os = "android"))]
2525
mod desktop;
26+
mod entryraw;
2627
mod error;
2728
mod file_path;
2829
#[cfg(target_os = "android")]
@@ -352,8 +353,8 @@ impl ScopeObject for scope::Entry {
352353
raw: Value,
353354
) -> std::result::Result<Self, Self::Error> {
354355
let path = serde_json::from_value(raw.into()).map(|raw| match raw {
355-
scope::EntryRaw::Value(path) => path,
356-
scope::EntryRaw::Object { path } => path,
356+
entryraw::EntryRaw::Value(path) => path,
357+
entryraw::EntryRaw::Object { path } => path,
357358
})?;
358359

359360
match app.path().parse(path) {
@@ -419,11 +420,13 @@ pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
419420
watcher::unwatch
420421
])
421422
.setup(|app, api| {
422-
let mut scope = Scope::default();
423-
scope.require_literal_leading_dot = api
424-
.config()
425-
.as_ref()
426-
.and_then(|c| c.require_literal_leading_dot);
423+
let scope = Scope {
424+
require_literal_leading_dot: api
425+
.config()
426+
.as_ref()
427+
.and_then(|c| c.require_literal_leading_dot),
428+
scope: Some(tauri::fs::Scope::new(app, &FsScope::default())?),
429+
};
427430

428431
#[cfg(target_os = "android")]
429432
{

0 commit comments

Comments
 (0)