Preserve target-native paths in command approvals (#42577)

## What changed

- Pass the selected executor's `PathUri` through user command approval requests instead of converting the working directory to a host-native path.
- Make native-path permission helpers explicitly local and require executor-aware permission transforms to receive a `FileSystemSandboxPolicyContext`.
- Cover approved remote commands to verify that the approval request reports the selected remote working directory and execution resumes after approval.

GitOrigin-RevId: 0aa3042f2d7594af6c7d0abf31d7f99cf67d5556
This commit is contained in:
iceweasel-oai authored and copyberry committed 2026-09-03 16:21:10 +00:00
1 parent 0650d6d1ca
commit 7a7c188682
30 files changed
+304 -368

No files matched your search

@@ -56,7 +56,8 @@ pub fn resolve_windows_deny_read_paths(
})
.collect(),
);
let Some(matcher) = ReadDenyMatcher::try_new(&glob_policy, cwd.as_path())? else {
let Some(matcher) = ReadDenyMatcher::try_new_for_local_paths(&glob_policy, cwd.as_path())?
else {
return Ok(paths);
};
@@ -72,7 +73,7 @@ pub fn resolve_windows_deny_read_paths(
let directory_scan_mode = if let Some(file_paths) = ripgrep_files(&scan_plan)? {
for path in file_paths {
if matcher.is_read_denied(&path) {
if matcher.is_local_path_read_denied(&path) {
push_absolute_path(&mut paths, &mut seen, path)?;
}
}
@@ -131,7 +132,8 @@ fn ripgrep_files(scan_plan: &GlobScanPlan) -> Result<Option<Vec<PathBuf>>, Strin
// Ripgrep uses exit 2 for traversal errors, including protected
// Windows directories. Its output may be incomplete. The caller
// must enumerate again using the matcher-backed walker; policy
// syntax has already been validated by ReadDenyMatcher::try_new.
// syntax has already been validated by
// ReadDenyMatcher::try_new_for_local_paths.
return Ok(None);
}
@@ -219,11 +219,11 @@ fn native_walk_preserves_canonical_matches_through_directory_links_and_cycles()
access: FileSystemAccessMode::Deny,
missing_path_behavior: None,
}]);
let matcher = ReadDenyMatcher::try_new(&policy, cwd.as_path())
let matcher = ReadDenyMatcher::try_new_for_local_paths(&policy, cwd.as_path())
.expect("valid matcher")
.expect("deny restriction");
assert!(
matcher.is_read_denied_with_canonical_path(
matcher.is_local_path_read_denied_with_canonical_path(
&alias.join("secret.env"),
&target
.canonicalize()
@@ -69,8 +69,8 @@ impl GlobWalker<'_> {
let denied = match canonical {
Some(canonical) => self
.matcher
.is_read_denied_with_canonical_path(path, canonical),
None => self.matcher.is_read_denied(path),
.is_local_path_read_denied_with_canonical_path(path, canonical),
None => self.matcher.is_local_path_read_denied(path),
};
if denied {
push_absolute_path(self.paths, self.seen_paths, path.to_path_buf())?;
@@ -114,7 +114,7 @@ impl ResolvedWindowsSandboxPermissions {
}) && cwd
.ancestors()
.last()
.is_some_and(|root| self.file_system.can_read_path_with_cwd(root, cwd))
.is_some_and(|root| self.file_system.can_read_local_path_with_cwd(root, cwd))
}
pub(crate) fn include_platform_defaults(&self) -> bool {