summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-10-04 20:55:41 +0100
committerGitHub <noreply@github.com>2024-10-04 20:55:41 +0100
commit2de4faa483982478e9a36ad4ab891a887b4779f1 (patch)
tree5ee8512e5dc380759054900943074d5b6ee8c65c
parentf288730c38bd4f13b464a9bd67eb901a8c790bc4 (diff)
refactor: improve node permission checks (#26028)
Does less work when requesting permissions with `-A`
-rw-r--r--cli/npm/byonm.rs12
-rw-r--r--cli/npm/managed/mod.rs7
-rw-r--r--cli/npm/managed/resolvers/common.rs40
-rw-r--r--cli/npm/managed/resolvers/global.rs6
-rw-r--r--cli/npm/managed/resolvers/local.rs6
-rw-r--r--ext/node/lib.rs12
-rw-r--r--ext/node/ops/require.rs24
-rw-r--r--ext/node/ops/worker_threads.rs12
-rw-r--r--runtime/permissions/lib.rs54
-rw-r--r--runtime/snapshot.rs3
-rw-r--r--tests/unit/permissions_test.ts166
11 files changed, 214 insertions, 128 deletions
diff --git a/cli/npm/byonm.rs b/cli/npm/byonm.rs
index 02c2e6da8..fc095ab16 100644
--- a/cli/npm/byonm.rs
+++ b/cli/npm/byonm.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
@@ -32,18 +33,19 @@ pub type CliByonmNpmResolver = ByonmNpmResolver<CliDenoResolverFs>;
struct CliByonmWrapper(Arc<CliByonmNpmResolver>);
impl NodeRequireResolver for CliByonmWrapper {
- fn ensure_read_permission(
+ fn ensure_read_permission<'a>(
&self,
permissions: &mut dyn NodePermissions,
- path: &Path,
- ) -> Result<(), AnyError> {
+ path: &'a Path,
+ ) -> Result<Cow<'a, Path>, AnyError> {
if !path
.components()
.any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules")
{
- _ = permissions.check_read_path(path)?;
+ permissions.check_read_path(path)
+ } else {
+ Ok(Cow::Borrowed(path))
}
- Ok(())
}
}
diff --git a/cli/npm/managed/mod.rs b/cli/npm/managed/mod.rs
index 225cd6c29..ec50a9c65 100644
--- a/cli/npm/managed/mod.rs
+++ b/cli/npm/managed/mod.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
@@ -593,11 +594,11 @@ impl NpmResolver for ManagedCliNpmResolver {
}
impl NodeRequireResolver for ManagedCliNpmResolver {
- fn ensure_read_permission(
+ fn ensure_read_permission<'a>(
&self,
permissions: &mut dyn NodePermissions,
- path: &Path,
- ) -> Result<(), AnyError> {
+ path: &'a Path,
+ ) -> Result<Cow<'a, Path>, AnyError> {
self.fs_resolver.ensure_read_permission(permissions, path)
}
}
diff --git a/cli/npm/managed/resolvers/common.rs b/cli/npm/managed/resolvers/common.rs
index 8df4debc5..867bb4168 100644
--- a/cli/npm/managed/resolvers/common.rs
+++ b/cli/npm/managed/resolvers/common.rs
@@ -3,6 +3,7 @@
pub mod bin_entries;
pub mod lifecycle_scripts;
+use std::borrow::Cow;
use std::collections::HashMap;
use std::io::ErrorKind;
use std::path::Path;
@@ -62,11 +63,12 @@ pub trait NpmPackageFsResolver: Send + Sync {
async fn cache_packages(&self) -> Result<(), AnyError>;
- fn ensure_read_permission(
+ #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
+ fn ensure_read_permission<'a>(
&self,
permissions: &mut dyn NodePermissions,
- path: &Path,
- ) -> Result<(), AnyError>;
+ path: &'a Path,
+ ) -> Result<Cow<'a, Path>, AnyError>;
}
#[derive(Debug)]
@@ -85,11 +87,15 @@ impl RegistryReadPermissionChecker {
}
}
- pub fn ensure_registry_read_permission(
+ pub fn ensure_registry_read_permission<'a>(
&self,
permissions: &mut dyn NodePermissions,
- path: &Path,
- ) -> Result<(), AnyError> {
+ path: &'a Path,
+ ) -> Result<Cow<'a, Path>, AnyError> {
+ if permissions.query_read_all() {
+ return Ok(Cow::Borrowed(path)); // skip permissions checks below
+ }
+
// allow reading if it's in the node_modules
let is_path_in_node_modules = path.starts_with(&self.registry_path)
&& path
@@ -118,20 +124,20 @@ impl RegistryReadPermissionChecker {
},
}
};
- let Some(registry_path_canon) = canonicalize(&self.registry_path)? else {
- return Ok(()); // not exists, allow reading
- };
- let Some(path_canon) = canonicalize(path)? else {
- return Ok(()); // not exists, allow reading
- };
-
- if path_canon.starts_with(registry_path_canon) {
- return Ok(());
+ if let Some(registry_path_canon) = canonicalize(&self.registry_path)? {
+ if let Some(path_canon) = canonicalize(path)? {
+ if path_canon.starts_with(registry_path_canon) {
+ return Ok(Cow::Owned(path_canon));
+ }
+ } else if path.starts_with(registry_path_canon)
+ || path.starts_with(&self.registry_path)
+ {
+ return Ok(Cow::Borrowed(path));
+ }
}
}
- _ = permissions.check_read_path(path)?;
- Ok(())
+ permissions.check_read_path(path)
}
}
diff --git a/cli/npm/managed/resolvers/global.rs b/cli/npm/managed/resolvers/global.rs
index ca5722c86..5be315e99 100644
--- a/cli/npm/managed/resolvers/global.rs
+++ b/cli/npm/managed/resolvers/global.rs
@@ -183,11 +183,11 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
Ok(())
}
- fn ensure_read_permission(
+ fn ensure_read_permission<'a>(
&self,
permissions: &mut dyn NodePermissions,
- path: &Path,
- ) -> Result<(), AnyError> {
+ path: &'a Path,
+ ) -> Result<Cow<'a, Path>, AnyError> {
self
.registry_read_permission_checker
.ensure_registry_read_permission(permissions, path)
diff --git a/cli/npm/managed/resolvers/local.rs b/cli/npm/managed/resolvers/local.rs
index 258c9bf3d..63a972a43 100644
--- a/cli/npm/managed/resolvers/local.rs
+++ b/cli/npm/managed/resolvers/local.rs
@@ -257,11 +257,11 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
.await
}
- fn ensure_read_permission(
+ fn ensure_read_permission<'a>(
&self,
permissions: &mut dyn NodePermissions,
- path: &Path,
- ) -> Result<(), AnyError> {
+ path: &'a Path,
+ ) -> Result<Cow<'a, Path>, AnyError> {
self
.registry_read_permission_checker
.ensure_registry_read_permission(permissions, path)
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index d23c07204..03462f36f 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -66,6 +66,7 @@ pub trait NodePermissions {
&mut self,
path: &'a Path,
) -> Result<Cow<'a, Path>, AnyError>;
+ fn query_read_all(&mut self) -> bool;
fn check_sys(&mut self, kind: &str, api_name: &str) -> Result<(), AnyError>;
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
fn check_write_with_api_name(
@@ -103,6 +104,10 @@ impl NodePermissions for deno_permissions::PermissionsContainer {
deno_permissions::PermissionsContainer::check_read_path(self, path, None)
}
+ fn query_read_all(&mut self) -> bool {
+ deno_permissions::PermissionsContainer::query_read_all(self)
+ }
+
#[inline(always)]
fn check_write_with_api_name(
&mut self,
@@ -124,11 +129,12 @@ pub type NodeRequireResolverRc =
deno_fs::sync::MaybeArc<dyn NodeRequireResolver>;
pub trait NodeRequireResolver: std::fmt::Debug + MaybeSend + MaybeSync {
- fn ensure_read_permission(
+ #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
+ fn ensure_read_permission<'a>(
&self,
permissions: &mut dyn NodePermissions,
- path: &Path,
- ) -> Result<(), AnyError>;
+ path: &'a Path,
+ ) -> Result<Cow<'a, Path>, AnyError>;
}
pub static NODE_ENV_VAR_ALLOWLIST: Lazy<HashSet<String>> = Lazy::new(|| {
diff --git a/ext/node/ops/require.rs b/ext/node/ops/require.rs
index 15667aae7..547336981 100644
--- a/ext/node/ops/require.rs
+++ b/ext/node/ops/require.rs
@@ -15,6 +15,7 @@ use deno_path_util::normalize_path;
use node_resolver::NodeModuleKind;
use node_resolver::NodeResolutionMode;
use node_resolver::REQUIRE_CONDITIONS;
+use std::borrow::Cow;
use std::cell::RefCell;
use std::path::Path;
use std::path::PathBuf;
@@ -25,10 +26,11 @@ use crate::NodeRequireResolverRc;
use crate::NodeResolverRc;
use crate::NpmResolverRc;
-fn ensure_read_permission<P>(
+#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
+fn ensure_read_permission<'a, P>(
state: &mut OpState,
- file_path: &Path,
-) -> Result<(), AnyError>
+ file_path: &'a Path,
+) -> Result<Cow<'a, Path>, AnyError>
where
P: NodePermissions + 'static,
{
@@ -107,7 +109,7 @@ where
deno_path_util::normalize_path(current_dir.join(from))
};
- ensure_read_permission::<P>(state, &from)?;
+ let from = ensure_read_permission::<P>(state, &from)?;
if cfg!(windows) {
// return root node_modules when path is 'D:\\'.
@@ -129,7 +131,7 @@ where
}
let mut paths = Vec::with_capacity(from.components().count());
- let mut current_path = from.as_path();
+ let mut current_path = from.as_ref();
let mut maybe_parent = Some(current_path);
while let Some(parent) = maybe_parent {
if !parent.ends_with("node_modules") {
@@ -267,7 +269,7 @@ where
P: NodePermissions + 'static,
{
let path = PathBuf::from(path);
- ensure_read_permission::<P>(state, &path)?;
+ let path = ensure_read_permission::<P>(state, &path)?;
let fs = state.borrow::<FileSystemRc>();
if let Ok(metadata) = fs.stat_sync(&path) {
if metadata.is_file {
@@ -290,7 +292,7 @@ where
P: NodePermissions + 'static,
{
let path = PathBuf::from(request);
- ensure_read_permission::<P>(state, &path)?;
+ let path = ensure_read_permission::<P>(state, &path)?;
let fs = state.borrow::<FileSystemRc>();
let canonicalized_path =
deno_core::strip_unc_prefix(fs.realpath_sync(&path)?);
@@ -362,7 +364,7 @@ where
if parent_id == "<repl>" || parent_id == "internal/preload" {
let fs = state.borrow::<FileSystemRc>();
if let Ok(cwd) = fs.cwd() {
- ensure_read_permission::<P>(state, &cwd)?;
+ let cwd = ensure_read_permission::<P>(state, &cwd)?;
return Ok(Some(cwd.to_string_lossy().into_owned()));
}
}
@@ -443,7 +445,7 @@ where
P: NodePermissions + 'static,
{
let file_path = PathBuf::from(file_path);
- ensure_read_permission::<P>(state, &file_path)?;
+ let file_path = ensure_read_permission::<P>(state, &file_path)?;
let fs = state.borrow::<FileSystemRc>();
Ok(fs.read_text_file_lossy_sync(&file_path, None)?)
}
@@ -528,7 +530,7 @@ where
P: NodePermissions + 'static,
{
let filename = PathBuf::from(filename);
- ensure_read_permission::<P>(state, filename.parent().unwrap())?;
+ // permissions: allow reading the closest package.json files
let node_resolver = state.borrow::<NodeResolverRc>().clone();
node_resolver
.get_closest_package_json_from_path(&filename)
@@ -567,7 +569,7 @@ where
P: NodePermissions + 'static,
{
let referrer_path = PathBuf::from(&referrer_filename);
- ensure_read_permission::<P>(state, &referrer_path)?;
+ let referrer_path = ensure_read_permission::<P>(state, &referrer_path)?;
let node_resolver = state.borrow::<NodeResolverRc>();
let Some(pkg) =
node_resolver.get_closest_package_json_from_path(&referrer_path)?
diff --git a/ext/node/ops/worker_threads.rs b/ext/node/ops/worker_threads.rs
index c7ea4c52c..4c50092f2 100644
--- a/ext/node/ops/worker_threads.rs
+++ b/ext/node/ops/worker_threads.rs
@@ -7,6 +7,7 @@ use deno_core::url::Url;
use deno_core::OpState;
use deno_fs::FileSystemRc;
use node_resolver::NodeResolution;
+use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
@@ -14,10 +15,11 @@ use crate::NodePermissions;
use crate::NodeRequireResolverRc;
use crate::NodeResolverRc;
-fn ensure_read_permission<P>(
+#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
+fn ensure_read_permission<'a, P>(
state: &mut OpState,
- file_path: &Path,
-) -> Result<(), AnyError>
+ file_path: &'a Path,
+) -> Result<Cow<'a, Path>, AnyError>
where
P: NodePermissions + 'static,
{
@@ -47,7 +49,7 @@ where
"Relative path entries must start with '.' or '..'",
));
}
- ensure_read_permission::<P>(state, &path)?;
+ let path = ensure_read_permission::<P>(state, &path)?;
let fs = state.borrow::<FileSystemRc>();
let canonicalized_path =
deno_core::strip_unc_prefix(fs.realpath_sync(&path)?);
@@ -57,7 +59,7 @@ where
let url_path = url
.to_file_path()
.map_err(|e| generic_error(format!("URL to Path-String: {:#?}", e)))?;
- ensure_read_permission::<P>(state, &url_path)?;
+ let url_path = ensure_read_permission::<P>(state, &url_path)?;
let fs = state.borrow::<FileSystemRc>();
if !fs.exists_sync(&url_path) {
return Err(generic_error(format!("File not found [{:?}]", url_path)));
diff --git a/runtime/permissions/lib.rs b/runtime/permissions/lib.rs
index efabd0b17..2904242da 100644
--- a/runtime/permissions/lib.rs
+++ b/runtime/permissions/lib.rs
@@ -2285,6 +2285,11 @@ impl PermissionsContainer {
self.inner.lock().read.check_all(Some(api_name))
}
+ #[inline(always)]
+ pub fn query_read_all(&self) -> bool {
+ self.inner.lock().read.query(None) == PermissionState::Granted
+ }
+
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
#[inline(always)]
pub fn check_write(
@@ -2614,8 +2619,13 @@ impl PermissionsContainer {
&self,
path: Option<&str>,
) -> Result<PermissionState, AnyError> {
+ let inner = self.inner.lock();
+ let permission = &inner.read;
+ if permission.is_allow_all() {
+ return Ok(PermissionState::Granted);
+ }
Ok(
- self.inner.lock().read.query(
+ permission.query(
path
.map(|path| {
Result::<_, AnyError>::Ok(
@@ -2633,8 +2643,13 @@ impl PermissionsContainer {
&self,
path: Option<&str>,
) -> Result<PermissionState, AnyError> {
+ let inner = self.inner.lock();
+ let permission = &inner.write;
+ if permission.is_allow_all() {
+ return Ok(PermissionState::Granted);
+ }
Ok(
- self.inner.lock().write.query(
+ permission.query(
path
.map(|path| {
Result::<_, AnyError>::Ok(
@@ -2652,8 +2667,13 @@ impl PermissionsContainer {
&self,
host: Option<&str>,
) -> Result<PermissionState, AnyError> {
+ let inner = self.inner.lock();
+ let permission = &inner.net;
+ if permission.is_allow_all() {
+ return Ok(PermissionState::Granted);
+ }
Ok(
- self.inner.lock().net.query(
+ permission.query(
match host {
None => None,
Some(h) => Some(self.descriptor_parser.parse_net_descriptor(h)?),
@@ -2665,7 +2685,12 @@ impl PermissionsContainer {
#[inline(always)]
pub fn query_env(&self, var: Option<&str>) -> PermissionState {
- self.inner.lock().env.query(var)
+ let inner = self.inner.lock();
+ let permission = &inner.env;
+ if permission.is_allow_all() {
+ return PermissionState::Granted;
+ }
+ permission.query(var)
}
#[inline(always)]
@@ -2673,8 +2698,13 @@ impl PermissionsContainer {
&self,
kind: Option<&str>,
) -> Result<PermissionState, AnyError> {
+ let inner = self.inner.lock();
+ let permission = &inner.sys;
+ if permission.is_allow_all() {
+ return Ok(PermissionState::Granted);
+ }
Ok(
- self.inner.lock().sys.query(
+ permission.query(
kind
.map(|kind| self.descriptor_parser.parse_sys_descriptor(kind))
.transpose()?
@@ -2688,8 +2718,13 @@ impl PermissionsContainer {
&self,
cmd: Option<&str>,
) -> Result<PermissionState, AnyError> {
+ let inner = self.inner.lock();
+ let permission = &inner.run;
+ if permission.is_allow_all() {
+ return Ok(PermissionState::Granted);
+ }
Ok(
- self.inner.lock().run.query(
+ permission.query(
cmd
.map(|request| self.descriptor_parser.parse_run_query(request))
.transpose()?
@@ -2703,8 +2738,13 @@ impl PermissionsContainer {
&self,
path: Option<&str>,
) -> Result<PermissionState, AnyError> {
+ let inner = self.inner.lock();
+ let permission = &inner.ffi;
+ if permission.is_allow_all() {
+ return Ok(PermissionState::Granted);
+ }
Ok(
- self.inner.lock().ffi.query(
+ permission.query(
path
.map(|path| {
Result::<_, AnyError>::Ok(
diff --git a/runtime/snapshot.rs b/runtime/snapshot.rs
index 456810e6a..041132f97 100644
--- a/runtime/snapshot.rs
+++ b/runtime/snapshot.rs
@@ -97,6 +97,9 @@ impl deno_node::NodePermissions for Permissions {
) -> Result<PathBuf, deno_core::error::AnyError> {
unreachable!("snapshotting!")
}
+ fn query_read_all(&mut self) -> bool {
+ unreachable!("snapshotting!")
+ }
fn check_write_with_api_name(
&mut self,
_p: &str,
diff --git a/tests/unit/permissions_test.ts b/tests/unit/permissions_test.ts
index 82524d556..f981b10fd 100644
--- a/tests/unit/permissions_test.ts
+++ b/tests/unit/permissions_test.ts
@@ -20,54 +20,72 @@ Deno.test(function permissionInvalidNameSync() {
}, TypeError);
});
-Deno.test(async function permissionNetInvalidHost() {
- await assertRejects(async () => {
- await Deno.permissions.query({ name: "net", host: ":" });
- }, URIError);
-});
-
-Deno.test(function permissionNetInvalidHostSync() {
- assertThrows(() => {
- Deno.permissions.querySync({ name: "net", host: ":" });
- }, URIError);
-});
-
-Deno.test(async function permissionSysValidKind() {
- await Deno.permissions.query({ name: "sys", kind: "loadavg" });
- await Deno.permissions.query({ name: "sys", kind: "osRelease" });
- await Deno.permissions.query({ name: "sys", kind: "osUptime" });
- await Deno.permissions.query({ name: "sys", kind: "networkInterfaces" });
- await Deno.permissions.query({ name: "sys", kind: "systemMemoryInfo" });
- await Deno.permissions.query({ name: "sys", kind: "hostname" });
- await Deno.permissions.query({ name: "sys", kind: "uid" });
- await Deno.permissions.query({ name: "sys", kind: "gid" });
- await Deno.permissions.query({ name: "sys", kind: "cpus" });
-});
-
-Deno.test(function permissionSysValidKindSync() {
- Deno.permissions.querySync({ name: "sys", kind: "loadavg" });
- Deno.permissions.querySync({ name: "sys", kind: "osRelease" });
- Deno.permissions.querySync({ name: "sys", kind: "networkInterfaces" });
- Deno.permissions.querySync({ name: "sys", kind: "systemMemoryInfo" });
- Deno.permissions.querySync({ name: "sys", kind: "hostname" });
- Deno.permissions.querySync({ name: "sys", kind: "uid" });
- Deno.permissions.querySync({ name: "sys", kind: "gid" });
- Deno.permissions.querySync({ name: "sys", kind: "cpus" });
-});
-
-Deno.test(async function permissionSysInvalidKind() {
- await assertRejects(async () => {
- // deno-lint-ignore no-explicit-any
- await Deno.permissions.query({ name: "sys", kind: "abc" as any });
- }, TypeError);
-});
-
-Deno.test(function permissionSysInvalidKindSync() {
- assertThrows(() => {
- // deno-lint-ignore no-explicit-any
- Deno.permissions.querySync({ name: "sys", kind: "abc" as any });
- }, TypeError);
-});
+Deno.test(
+ { permissions: { net: [] } },
+ async function permissionNetInvalidHost() {
+ await assertRejects(async () => {
+ await Deno.permissions.query({ name: "net", host: ":" });
+ }, URIError);
+ },
+);
+
+Deno.test(
+ { permissions: { net: [] } },
+ function permissionNetInvalidHostSync() {
+ assertThrows(() => {
+ Deno.permissions.querySync({ name: "net", host: ":" });
+ }, URIError);
+ },
+);
+
+Deno.test(
+ { permissions: { sys: [] } },
+ async function permissionSysValidKind() {
+ await Deno.permissions.query({ name: "sys", kind: "loadavg" });
+ await Deno.permissions.query({ name: "sys", kind: "osRelease" });
+ await Deno.permissions.query({ name: "sys", kind: "osUptime" });
+ await Deno.permissions.query({ name: "sys", kind: "networkInterfaces" });
+ await Deno.permissions.query({ name: "sys", kind: "systemMemoryInfo" });
+ await Deno.permissions.query({ name: "sys", kind: "hostname" });
+ await Deno.permissions.query({ name: "sys", kind: "uid" });
+ await Deno.permissions.query({ name: "sys", kind: "gid" });
+ await Deno.permissions.query({ name: "sys", kind: "cpus" });
+ },
+);
+
+Deno.test(
+ { permissions: { sys: [] } },
+ function permissionSysValidKindSync() {
+ Deno.permissions.querySync({ name: "sys", kind: "loadavg" });
+ Deno.permissions.querySync({ name: "sys", kind: "osRelease" });
+ Deno.permissions.querySync({ name: "sys", kind: "networkInterfaces" });
+ Deno.permissions.querySync({ name: "sys", kind: "systemMemoryInfo" });
+ Deno.permissions.querySync({ name: "sys", kind: "hostname" });
+ Deno.permissions.querySync({ name: "sys", kind: "uid" });
+ Deno.permissions.querySync({ name: "sys", kind: "gid" });
+ Deno.permissions.querySync({ name: "sys", kind: "cpus" });
+ },
+);
+
+Deno.test(
+ { permissions: { sys: [] } },
+ async function permissionSysInvalidKind() {
+ await assertRejects(async () => {
+ // deno-lint-ignore no-explicit-any
+ await Deno.permissions.query({ name: "sys", kind: "abc" as any });
+ }, TypeError);
+ },
+);
+
+Deno.test(
+ { permissions: { sys: [] } },
+ function permissionSysInvalidKindSync() {
+ assertThrows(() => {
+ // deno-lint-ignore no-explicit-any
+ Deno.permissions.querySync({ name: "sys", kind: "abc" as any });
+ }, TypeError);
+ },
+);
Deno.test(async function permissionQueryReturnsEventTarget() {
const status = await Deno.permissions.query({ name: "read", path: "." });
@@ -134,29 +152,35 @@ Deno.test(function permissionStatusIllegalConstructor() {
});
// Regression test for https://github.com/denoland/deno/issues/17020
-Deno.test(async function permissionURL() {
- const path = new URL(".", import.meta.url);
-
- await Deno.permissions.query({ name: "read", path });
- await Deno.permissions.query({ name: "write", path });
- await Deno.permissions.query({ name: "ffi", path });
- await Deno.permissions.query({ name: "run", command: path });
-});
-
-Deno.test(function permissionURLSync() {
- Deno.permissions.querySync({
- name: "read",
- path: new URL(".", import.meta.url),
- });
- Deno.permissions.querySync({
- name: "write",
- path: new URL(".", import.meta.url),
- });
- Deno.permissions.querySync({
- name: "run",
- command: new URL(".", import.meta.url),
- });
-});
+Deno.test(
+ { permissions: { read: [], write: [], ffi: [], run: [] } },
+ async function permissionURL() {
+ const path = new URL(".", import.meta.url);
+
+ await Deno.permissions.query({ name: "read", path });
+ await Deno.permissions.query({ name: "write", path });
+ await Deno.permissions.query({ name: "ffi", path });
+ await Deno.permissions.query({ name: "run", command: path });
+ },
+);
+
+Deno.test(
+ { permissions: { read: [], write: [], ffi: [], run: [] } },
+ function permissionURLSync() {
+ Deno.permissions.querySync({
+ name: "read",
+ path: new URL(".", import.meta.url),
+ });
+ Deno.permissions.querySync({
+ name: "write",
+ path: new URL(".", import.meta.url),
+ });
+ Deno.permissions.querySync({
+ name: "run",
+ command: new URL(".", import.meta.url),
+ });
+ },
+);
Deno.test(async function permissionDescriptorValidation() {
for (const value of [undefined, null, {}]) {