Honor legacy :project_roots permission entries (#38916)

## Why

Permission profiles written before the rename to `:workspace_roots` can still
contain `:project_roots`. Treating that token as unknown ignores its entries and
can drop filesystem restrictions.

## What changed

- Parse `:project_roots` as an alias for `:workspace_roots`.
- Cover deny rules and read-only subpath carveouts in legacy profiles.

GitOrigin-RevId: 10aafc9e15372d1a8bcc2dbcf3ad7cc987f4e67e
This commit is contained in:
iceweasel-oai
2026-08-16 23:52:30 +00:00
committed by copyberry
parent cd8dc1e9b6
commit 772e88c8ae
2 changed files with 54 additions and 1 deletions

View File

@@ -779,7 +779,10 @@ fn parse_special_path(path: &str) -> Option<FileSystemSpecialPath> {
match path {
":root" => Some(FileSystemSpecialPath::Root),
":minimal" => Some(FileSystemSpecialPath::Minimal),
":workspace_roots" => Some(FileSystemSpecialPath::project_roots(/*subpath*/ None)),
// `:project_roots` shipped before the canonical rename; keep it as an alias.
":project_roots" | ":workspace_roots" => {
Some(FileSystemSpecialPath::project_roots(/*subpath*/ None))
}
":tmpdir" => Some(FileSystemSpecialPath::Tmpdir),
":slash_tmp" => Some(FileSystemSpecialPath::SlashTmp),
_ if path.starts_with(':') => {

View File

@@ -466,6 +466,56 @@ fn compile_permission_profile_workspace_roots_resolves_enabled_entries() -> std:
Ok(())
}
#[test]
fn legacy_project_roots_restrictions_do_not_fail_open() -> std::io::Result<()> {
let permissions = toml::from_str::<PermissionsToml>(
r#"
[read_deny.filesystem]
":root" = "read"
":project_roots" = "none"
[write_deny.filesystem]
":root" = "write"
":project_roots" = "none"
[write_read.filesystem]
":root" = "write"
[write_read.filesystem.":project_roots"]
docs = "read"
"#,
)
.expect("legacy project roots profiles should deserialize");
let cwd = TempDir::new()?;
let docs = cwd.path().join("docs");
let mut startup_warnings = Vec::new();
let (read_deny_policy, _) =
compile_permission_profile(&permissions, "read_deny", &mut startup_warnings)?;
assert_eq!(
read_deny_policy.resolve_access_with_cwd(cwd.path(), cwd.path()),
FileSystemAccessMode::Deny
);
let (write_deny_policy, _) =
compile_permission_profile(&permissions, "write_deny", &mut startup_warnings)?;
assert!(!write_deny_policy.has_full_disk_write_access());
assert_eq!(
write_deny_policy.resolve_access_with_cwd(cwd.path(), cwd.path()),
FileSystemAccessMode::Deny
);
let (write_read_policy, _) =
compile_permission_profile(&permissions, "write_read", &mut startup_warnings)?;
assert!(!write_read_policy.has_full_disk_write_access());
assert_eq!(
write_read_policy.resolve_access_with_cwd(&docs, cwd.path()),
FileSystemAccessMode::Read
);
Ok(())
}
#[test]
fn read_write_glob_warnings_skip_supported_deny_read_globs_and_trailing_subpaths() {
let filesystem = FilesystemPermissionsToml {