Bläddra i källkod

cache current binary path much sooner (#45)

* use ctor to cache starting executable

* clean up symlink checking logic

* changefile

* use wrapper for the static, put it in tauri_utils

* cargo +nightly fmt

* add license header to `StartingBinary`

* fix clippy warning

* fix: test

* simplify macOS dangerous flag detection

* update restart test to allow expected failure on macOS

* finish documentation

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
chip 3 år sedan
förälder
incheckning
7c3db7a381

+ 6 - 0
.changes/current-binary-caching.md

@@ -0,0 +1,6 @@
+---
+tauri: patch
+tauri-utils: patch
+---
+
+The path returned from `tauri::api::process::current_binary` is now cached when loading the binary.

+ 2 - 0
core/tauri-utils/Cargo.toml

@@ -30,6 +30,7 @@ aes-gcm = { version = "0.9", optional = true }
 ring = { version = "0.16", optional = true, features = ["std"] }
 once_cell = { version = "1.8", optional = true }
 serialize-to-javascript = { git = "https://github.com/chippers/serialize-to-javascript" }
+ctor = "0.1"
 
 [target."cfg(target_os = \"linux\")".dependencies]
 heck = "0.4"
@@ -39,3 +40,4 @@ build = [ "proc-macro2", "quote" ]
 compression = [ "zstd" ]
 schema = ["schemars"]
 isolation = [ "aes-gcm", "ring", "once_cell" ]
+process-relaunch-dangerous-allow-symlink-macos = []

+ 13 - 0
core/tauri-utils/src/config.rs

@@ -1260,6 +1260,12 @@ pub struct ProcessAllowlistConfig {
   /// Enables the relaunch API.
   #[serde(default)]
   pub relaunch: bool,
+  /// Dangerous option that allows macOS to relaunch even if the binary contains a symlink.
+  ///
+  /// This is due to macOS having less symlink protection. Highly recommended to not set this flag
+  /// unless you have a very specific reason too, and understand the implications of it.
+  #[serde(default)]
+  pub relaunch_dangerous_allow_symlink_macos: bool,
   /// Enables the exit API.
   #[serde(default)]
   pub exit: bool,
@@ -1270,6 +1276,7 @@ impl Allowlist for ProcessAllowlistConfig {
     let allowlist = Self {
       all: false,
       relaunch: true,
+      relaunch_dangerous_allow_symlink_macos: false,
       exit: true,
     };
     let mut features = allowlist.to_features();
@@ -1283,6 +1290,12 @@ impl Allowlist for ProcessAllowlistConfig {
     } else {
       let mut features = Vec::new();
       check_feature!(self, features, relaunch, "process-relaunch");
+      check_feature!(
+        self,
+        features,
+        relaunch_dangerous_allow_symlink_macos,
+        "process-relaunch-dangerous-allow-symlink-macos"
+      );
       check_feature!(self, features, exit, "process-exit");
       features
     }

+ 4 - 3
core/tauri-utils/src/lib.rs

@@ -68,14 +68,15 @@ impl Default for Env {
         // an AppImage is mounted to `/$TEMPDIR/.mount_${appPrefix}${hash}`
         // see https://github.com/AppImage/AppImageKit/blob/1681fd84dbe09c7d9b22e13cdb16ea601aa0ec47/src/runtime.c#L501
         // note that it is safe to use `std::env::current_exe` here since we just loaded an AppImage.
-        if !std::env::current_exe()
+        let is_temp = std::env::current_exe()
           .map(|p| {
             p.display()
               .to_string()
               .starts_with(&format!("{}/.mount_", std::env::temp_dir().display()))
           })
-          .unwrap_or(true)
-        {
+          .unwrap_or(true);
+
+        if !is_temp {
           panic!("`APPDIR` or `APPIMAGE` environment variable found but this application was not detected as an AppImage; this might be a security issue.");
         }
       }

+ 73 - 7
core/tauri-utils/src/platform.rs

@@ -8,16 +8,82 @@ use std::path::{PathBuf, MAIN_SEPARATOR};
 
 use crate::{Env, PackageInfo};
 
-/// Gets the path to the current executable, resolving symbolic links for security reasons.
+mod starting_binary;
+
+/// Retrieves the currently running binary's path, taking into account security considerations.
+///
+/// The path is cached as soon as possible (before even `main` runs) and that value is returned
+/// repeatedly instead of fetching the path every time. It is possible for the path to not be found,
+/// or explicitly disabled (see following macOS specific behavior).
+///
+/// # Platform-specific behavior
+///
+/// On `macOS`, this function will return an error if the original path contained any symlinks
+/// due to less protection on macOS regarding symlinks. This behavior can be disabled by setting the
+/// `process-relaunch-dangerous-allow-symlink-macos` feature, although it is *highly discouraged*.
+///
+/// # Security
+///
+/// If the above platform-specific behavior does **not** take place, this function uses the
+/// following resolution.
+///
+/// We canonicalize the path we received from [`std::env::current_exe`] to resolve any soft links.
+/// This avoids the usual issue of needing the file to exist at the passed path because a valid
+/// current executable result for our purpose should always exist. Notably,
+/// [`std::env::current_exe`] also has a security section that goes over a theoretical attack using
+/// hard links. Let's cover some specific topics that relate to different ways an attacker might
+/// try to trick this function into returning the wrong binary path.
+///
+/// ## Symlinks ("Soft Links")
+///
+/// [`std::path::Path::canonicalize`] is used to resolve symbolic links to the original path,
+/// including nested symbolic links (`link2 -> link1 -> bin`). On macOS, any results that include
+/// a symlink are rejected by default due to lesser symlink protections. This can be disabled,
+/// **although discouraged**, with the `process-relaunch-dangerous-allow-symlink-macos` feature.
+///
+/// ## Hard Links
+///
+/// A [Hard Link] is a named entry that points to a file in the file system.
+/// On most systems, this is what you would think of as a "file". The term is
+/// used on filesystems that allow multiple entries to point to the same file.
+/// The linked [Hard Link] Wikipedia page provides a decent overview.
+///
+/// In short, unless the attacker was able to create the link with elevated
+/// permissions, it should generally not be possible for them to hard link
+/// to a file they do not have permissions to - with exception to possible
+/// operating system exploits.
+///
+/// There are also some platform-specific information about this below.
+///
+/// ### Windows
+///
+/// Windows requires a permission to be set for the user to create a symlink
+/// or a hard link, regardless of ownership status of the target. Elevated
+/// permissions users have the ability to create them.
+///
+/// ### macOS
+///
+/// macOS allows for the creation of symlinks and hard links to any file.
+/// Accessing through those links will fail if the user who owns the links
+/// does not have the proper permissions on the original file.
+///
+/// ### Linux
+///
+/// Linux allows for the creation of symlinks to any file. Accessing the
+/// symlink will fail if the user who owns the symlink does not have the
+/// proper permissions on the original file.
 ///
-/// See https://doc.rust-lang.org/std/env/fn.current_exe.html#security for
-/// an example of what to be careful of when using `current_exe` output.
+/// Linux additionally provides a kernel hardening feature since version
+/// 3.6 (30 September 2012). Most distributions since then have enabled
+/// the protection (setting `fs.protected_hardlinks = 1`) by default, which
+/// means that a vast majority of desktop Linux users should have it enabled.
+/// **The feature prevents the creation of hardlinks that the user does not own
+/// or have read/write access to.** [See the patch that enabled this].
 ///
-/// We canonicalize the path we received from `current_exe` to resolve any
-/// soft links. it avoids the usual issue of needing the file to exist at
-/// the passed path because a valid `current_exe` result should always exist.
+/// [Hard Link]: https://en.wikipedia.org/wiki/Hard_link
+/// [See the patch that enabled this]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=800179c9b8a1e796e441674776d11cd4c05d61d7
 pub fn current_exe() -> std::io::Result<PathBuf> {
-  std::env::current_exe().and_then(|path| path.canonicalize())
+  self::starting_binary::STARTING_BINARY.cloned()
 }
 
 /// Try to determine the current target triple.

+ 76 - 0
core/tauri-utils/src/platform/starting_binary.rs

@@ -0,0 +1,76 @@
+// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-License-Identifier: MIT
+
+use ctor::ctor;
+use std::{
+  io::{Error, ErrorKind, Result},
+  path::{Path, PathBuf},
+};
+
+/// A cached version of the current binary using [`ctor`] to cache it before even `main` runs.
+#[ctor]
+#[used]
+pub(super) static STARTING_BINARY: StartingBinary = StartingBinary::new();
+
+/// Represents a binary path that was cached when the program was loaded.
+pub(super) struct StartingBinary(std::io::Result<PathBuf>);
+
+impl StartingBinary {
+  /// Find the starting executable as safely as possible.
+  fn new() -> Self {
+    // see notes on current_exe() for security implications
+    let dangerous_path = match std::env::current_exe() {
+      Ok(dangerous_path) => dangerous_path,
+      error @ Err(_) => return Self(error),
+    };
+
+    // note: this only checks symlinks on problematic platforms, see implementation below
+    if let Some(symlink) = Self::has_symlink(&dangerous_path) {
+      return Self(Err(Error::new(
+        ErrorKind::InvalidData,
+        format!("StartingBinary found current_exe() that contains a symlink on a non-allowed platform: {}", symlink.display()),
+      )));
+    }
+
+    // we canonicalize the path to resolve any symlinks to the real exe path
+    Self(dangerous_path.canonicalize())
+  }
+
+  /// A clone of the [`PathBuf`] found to be the starting path.
+  ///
+  /// Because [`Error`] is not clone-able, it is recreated instead.
+  pub(super) fn cloned(&self) -> Result<PathBuf> {
+    self
+      .0
+      .as_ref()
+      .map(Clone::clone)
+      .map_err(|e| Error::new(e.kind(), e.to_string()))
+  }
+
+  /// We only care about checking this on macOS currently, as it has the least symlink protections.
+  #[cfg(any(
+    not(target_os = "macos"),
+    feature = "process-relaunch-dangerous-allow-symlink-macos"
+  ))]
+  fn has_symlink(_: &Path) -> Option<&Path> {
+    None
+  }
+
+  /// We only care about checking this on macOS currently, as it has the least symlink protections.
+  #[cfg(all(
+    target_os = "macos",
+    not(feature = "process-relaunch-dangerous-allow-symlink-macos")
+  ))]
+  fn has_symlink(path: &Path) -> Option<&Path> {
+    path.ancestors().find(|ancestor| {
+      matches!(
+        ancestor
+          .symlink_metadata()
+          .as_ref()
+          .map(std::fs::Metadata::is_symlink),
+        Ok(true)
+      )
+    })
+  }
+}

+ 2 - 1
core/tauri/Cargo.toml

@@ -101,7 +101,7 @@ tokio-test = "0.4.2"
 tokio = { version = "1.15", features = [ "full" ] }
 
 [target."cfg(windows)".dev-dependencies.windows]
-version = "0.29.0"
+version = "0.30.0"
 features = [
   "Win32_Foundation",
 ]
@@ -172,6 +172,7 @@ path-all = []
 process-all = ["process-relaunch", "process-exit"]
 process-exit = []
 process-relaunch = []
+process-relaunch-dangerous-allow-symlink-macos = ["tauri-utils/process-relaunch-dangerous-allow-symlink-macos"]
 protocol-all = ["protocol-asset"]
 protocol-asset = []
 shell-all = ["shell-execute", "shell-sidecar", "shell-open"]

+ 1 - 0
core/tauri/build.rs

@@ -90,6 +90,7 @@ fn main() {
     // process
     process_all: { any(api_all, feature = "process-all") },
     process_relaunch: { any(protocol_all, feature = "process-relaunch") },
+    process_relaunch_dangerous_allow_symlink_macos: { feature = "process-relaunch-dangerous-allow-symlink-macos" },
     process_exit: { any(protocol_all, feature = "process-exit") },
 
     // clipboard

+ 21 - 58
core/tauri/src/api/process.rs

@@ -17,83 +17,46 @@ pub use command::*;
 
 /// Finds the current running binary's path.
 ///
-/// # Platform-specific behavior
-///
-/// On the `Linux` platform, this function will also **attempt** to detect if
-/// it's currently running from a valid [AppImage] and use that path instead.
-///
-/// # Security
-///
-/// If the above Platform-specific behavior does not take place, this function
-/// uses [`std::env::current_exe`]. Notably, it also has a security section
-/// that goes over a theoretical attack using hard links. Let's cover some
-/// specific topics that relate to different ways an attacker might try to
-/// trick this function into returning the wrong binary path.
-///
-/// ## Symlinks ("Soft Links")
-///
-/// [`std::path::Path::canonicalize`] is used to resolve symbolic links to the
-/// original path, including nested symbolic links (`link2 -> link1 -> bin`).
+/// With exception to any following platform-specific behavior, the path is cached as soon as
+/// possible, and then used repeatedly instead of querying for a new path every time this function
+/// is called.
 ///
-/// ## Hard Links
-///
-/// A [Hard Link] is a named entry that points to a file in the file system.
-/// On most systems, this is what you would think of as a "file". The term is
-/// used on filesystems that allow multiple entries to point to the same file.
-/// The linked [Hard Link] Wikipedia page provides a decent overview.
-///
-/// In short, unless the attacker was able to create the link with elevated
-/// permissions, it should generally not be possible for them to hard link
-/// to a file they do not have permissions to - with exception to possible
-/// operating system exploits.
-///
-/// There are also some platform-specific information about this below.
-///
-/// ### Windows
+/// # Platform-specific behavior
 ///
-/// Windows requires a permission to be set for the user to create a symlink
-/// or a hard link, regardless of ownership status of the target. Elevated
-/// permissions users have the ability to create them.
+/// ## Linux
 ///
-/// ### macOS
+/// On Linux, this function will **attempt** to detect if it's currently running from a
+/// valid [AppImage] and use that path instead.
 ///
-/// macOS allows for the creation of symlinks and hard links to any file.
-/// Accessing through those links will fail if the user who owns the links
-/// does not have the proper permissions on the original file.
+/// ## macOS
 ///
-/// ### Linux
+/// On `macOS`, this function will return an error if the original path contained any symlinks
+/// due to less protection on macOS regarding symlinks. This behavior can be disabled by setting the
+/// `process-relaunch-dangerous-allow-symlink-macos` feature, although it is *highly discouraged*.
 ///
-/// Linux allows for the creation of symlinks to any file. Accessing the
-/// symlink will fail if the user who owns the symlink does not have the
-/// proper permissions on the original file.
+/// # Security
 ///
-/// Linux additionally provides a kernel hardening feature since version
-/// 3.6 (30 September 2012). Most distributions since then have enabled
-/// the protection (setting `fs.protected_hardlinks = 1`) by default, which
-/// means that a vast majority of desktop Linux users should have it enabled.
-/// **The feature prevents the creation of hardlinks that the user does not own
-/// or have read/write access to.** [See the patch that enabled this.](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=800179c9b8a1e796e441674776d11cd4c05d61d7)
+/// See [`tauri_utils::platform::current_exe`] for possible security implications.
 ///
 /// [AppImage]: https://appimage.org/
-/// [Hard Link]: https://en.wikipedia.org/wiki/Hard_link
-#[allow(unused_variables)]
-pub fn current_binary(env: &Env) -> Option<PathBuf> {
+pub fn current_binary(_env: &Env) -> std::io::Result<PathBuf> {
   // if we are running from an AppImage, we ONLY want the set AppImage path
   #[cfg(target_os = "linux")]
-  if let Some(app_image_path) = &env.appimage {
-    return Some(PathBuf::from(app_image_path));
+  if let Some(app_image_path) = &_env.appimage {
+    return Ok(PathBuf::from(app_image_path));
   }
 
-  tauri_utils::platform::current_exe().ok()
+  tauri_utils::platform::current_exe()
 }
 
-/// Restarts the process.
+/// Restarts the currently running binary.
 ///
-/// See [`current_binary`] for the possible security implications.
+/// See [`current_binary`] for platform specific behavior, and
+/// [`tauri_utils::platform::current_exe`] for possible security implications.
 pub fn restart(env: &Env) {
   use std::process::{exit, Command};
 
-  if let Some(path) = current_binary(env) {
+  if let Ok(path) = current_binary(env) {
     Command::new(path)
       .spawn()
       .expect("application failed to start");

+ 9 - 7
core/tauri/src/scope/shell.rs

@@ -146,13 +146,15 @@ impl Scope {
           }
         })
         .collect(),
-      (Some(list), arg) if arg.is_empty() && list.iter().all(ShellScopeAllowedArg::is_fixed) => list
-        .iter()
-        .map(|arg| match arg {
-          ShellScopeAllowedArg::Fixed(fixed) => Ok(fixed.to_string()),
-          _ => unreachable!(),
-        })
-        .collect(),
+      (Some(list), arg) if arg.is_empty() && list.iter().all(ShellScopeAllowedArg::is_fixed) => {
+        list
+          .iter()
+          .map(|arg| match arg {
+            ShellScopeAllowedArg::Fixed(fixed) => Ok(fixed.to_string()),
+            _ => unreachable!(),
+          })
+          .collect()
+      }
       (Some(list), _) if list.is_empty() => Err(ScopeError::InvalidInput(command_name.into())),
       (Some(_), _) => Err(ScopeError::InvalidInput(command_name.into())),
     }?;

+ 31 - 5
core/tauri/tests/restart.rs

@@ -37,6 +37,14 @@ fn compile_restart_test_binary() -> io::Result<PathBuf> {
   cargo.arg("--manifest-path");
   cargo.arg(project.join("Cargo.toml"));
 
+  // enable the dangerous macos flag on tauri if the test runner has the feature enabled
+  if cfg!(feature = "process-relaunch-dangerous-allow-symlink-macos") {
+    cargo.args([
+      "--features",
+      "tauri/process-relaunch-dangerous-allow-symlink-macos",
+    ]);
+  }
+
   let status = cargo.status()?;
   if !status.success() {
     return Err(io::Error::new(
@@ -81,14 +89,32 @@ fn symlink_runner(create_symlinks: impl Fn(&Path) -> io::Result<Symlink>) -> Res
     // add the restart parameter so that the invocation will call tauri::api::process::restart
     cmd.arg("restart");
 
-    // gather the output into a string
-    let output = String::from_utf8(cmd.output()?.stdout)?;
+    let output = cmd.output()?;
 
-    // run destructors to prevent resource leaking if the assertion fails
+    // run `TempDir` destructors to prevent resource leaking if the assertion fails
     drop(temp);
 
-    // we expect the output to be the bin path, twice
-    assert_eq!(output, format!("{bin}\n{bin}\n", bin = bin.display()));
+    if output.status.success() {
+      // gather the output into a string
+      let stdout = String::from_utf8(output.stdout)?;
+
+      // we expect the output to be the bin path, twice
+      assert_eq!(stdout, format!("{bin}\n{bin}\n", bin = bin.display()));
+    } else if cfg!(all(
+      target_os = "macos",
+      not(feature = "process-relaunch-dangerous-allow-symlink-macos")
+    )) {
+      // we expect this to fail on macOS without the dangerous symlink flag set
+      let stderr = String::from_utf8(output.stderr)?;
+
+      // make sure it's the error that we expect
+      assert!(stderr.contains(
+        "StartingBinary found current_exe() that contains a symlink on a non-allowed platform"
+      ));
+    } else {
+      // we didn't expect the program to fail in this configuration, just panic
+      panic!("restart integration test runner failed for unknown reason");
+    }
   }
 
   Ok(())

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 189 - 253
core/tauri/tests/restart/Cargo.lock


+ 17 - 6
tooling/cli.rs/Cargo.lock

@@ -20,7 +20,7 @@ version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
 dependencies = [
- "generic-array 0.14.5",
+ "generic-array 0.14.4",
 ]
 
 [[package]]
@@ -153,7 +153,7 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95"
 dependencies = [
- "generic-array 0.14.5",
+ "generic-array 0.14.4",
 ]
 
 [[package]]
@@ -454,6 +454,16 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "ctor"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
+dependencies = [
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "ctr"
 version = "0.8.0"
@@ -548,7 +558,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
 dependencies = [
- "generic-array 0.14.5",
+ "generic-array 0.14.4",
 ]
 
 [[package]]
@@ -559,7 +569,7 @@ checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b"
 dependencies = [
  "block-buffer 0.10.0",
  "crypto-common",
- "generic-array 0.14.5",
+ "generic-array 0.14.4",
  "subtle",
 ]
 
@@ -2384,7 +2394,7 @@ dependencies = [
  "regex",
  "serde",
  "serde_json",
- "sha2 0.10.1",
+ "sha2 0.9.9",
  "strsim",
  "tar",
  "tempfile",
@@ -2445,6 +2455,7 @@ version = "1.0.0-beta.3"
 dependencies = [
  "aes-gcm",
  "base64",
+ "ctor",
  "heck",
  "html5ever",
  "kuchiki",
@@ -2657,7 +2668,7 @@ version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
 dependencies = [
- "generic-array 0.14.5",
+ "generic-array 0.14.4",
  "subtle",
 ]
 

+ 20 - 28
tooling/cli.rs/schema.json

@@ -65,9 +65,7 @@
             "removeDir": false,
             "removeFile": false,
             "renameFile": false,
-            "scope": [
-              "$APP/**"
-            ],
+            "scope": [],
             "writeFile": false
           },
           "globalShortcut": {
@@ -90,14 +88,13 @@
           "process": {
             "all": false,
             "exit": false,
-            "relaunch": false
+            "relaunch": false,
+            "relaunchDangerousAllowSymlinkMacos": false
           },
           "protocol": {
             "all": false,
             "asset": false,
-            "assetScope": [
-              "$APP/**"
-            ]
+            "assetScope": []
           },
           "shell": {
             "all": false,
@@ -244,9 +241,7 @@
             "removeDir": false,
             "removeFile": false,
             "renameFile": false,
-            "scope": [
-              "$APP/**"
-            ],
+            "scope": [],
             "writeFile": false
           },
           "allOf": [
@@ -317,7 +312,8 @@
           "default": {
             "all": false,
             "exit": false,
-            "relaunch": false
+            "relaunch": false,
+            "relaunchDangerousAllowSymlinkMacos": false
           },
           "allOf": [
             {
@@ -330,9 +326,7 @@
           "default": {
             "all": false,
             "asset": false,
-            "assetScope": [
-              "$APP/**"
-            ]
+            "assetScope": []
           },
           "allOf": [
             {
@@ -1003,9 +997,7 @@
         },
         "scope": {
           "description": "The access scope for the filesystem APIs.",
-          "default": [
-            "$APP/**"
-          ],
+          "default": [],
           "allOf": [
             {
               "$ref": "#/definitions/FsAllowlistScope"
@@ -1066,7 +1058,7 @@
       "additionalProperties": false
     },
     "HttpAllowlistScope": {
-      "description": "HTTP API scope definition. It is a list of URLs that can be accessed by the webview when using the HTTP APIs.",
+      "description": "HTTP API scope definition. It is a list of URLs that can be accessed by the webview when using the HTTP APIs. The URL path is matched against the request URL using a glob pattern.",
       "type": "array",
       "items": {
         "type": "string",
@@ -1259,6 +1251,11 @@
           "description": "Enables the relaunch API.",
           "default": false,
           "type": "boolean"
+        },
+        "relaunchDangerousAllowSymlinkMacos": {
+          "description": "Dangerous option that allows macOS to relaunch even if the binary contains a symlink.\n\nThis is due to macOS having less symlink protection. Highly recommended to not set this flag unless you have a very specific reason too, and understand the implications of it.",
+          "default": false,
+          "type": "boolean"
         }
       },
       "additionalProperties": false
@@ -1279,9 +1276,7 @@
         },
         "assetScope": {
           "description": "The access scope for the asset protocol.",
-          "default": [
-            "$APP/**"
-          ],
+          "default": [],
           "allOf": [
             {
               "$ref": "#/definitions/FsAllowlistScope"
@@ -1505,9 +1500,7 @@
               "removeDir": false,
               "removeFile": false,
               "renameFile": false,
-              "scope": [
-                "$APP/**"
-              ],
+              "scope": [],
               "writeFile": false
             },
             "globalShortcut": {
@@ -1530,14 +1523,13 @@
             "process": {
               "all": false,
               "exit": false,
-              "relaunch": false
+              "relaunch": false,
+              "relaunchDangerousAllowSymlinkMacos": false
             },
             "protocol": {
               "all": false,
               "asset": false,
-              "assetScope": [
-                "$APP/**"
-              ]
+              "assetScope": []
             },
             "shell": {
               "all": false,

Vissa filer visades inte eftersom för många filer har ändrats