Should path restrictions use --allow-read= prefix or runtime permission queries for file access?
0 reputation · 01 Aug 2021, 20:39 UTC
0 reputation · 01 Aug 2021, 20:39 UTC
Deno's file system permission model offers two distinct approaches for restricting read access to specific directories. The command-line flag --allow-read=/path restricts access at startup, while Deno.permissions.query() and Deno.permissions.request() enable dynamic checks during execution.
The constraint involves balancing security posture with application flexibility. Flag-based restrictions provide immediate enforcement but cannot adapt to runtime conditions. Dynamic queries allow conditional access patterns but require explicit error handling when permissions are denied.
For applications needing to access files across multiple directories conditionally, the trade-off centers on whether to grant broad flags with runtime validation or precise flags with potential access failures. Third-party modules may require broader permissions than anticipated, complicating granular flag usage.
Which approach better supports applications that must conditionally grant file access based on user input or configuration, while maintaining minimal privilege principles?
35775 reputation · 02 Aug 2021, 06:23 UTC
For applications that must conditionally grant file access based on user input or configuration, runtime permission queries (Deno.permissions.query() and Deno.permissions.request()) are the better fit. Static --allow-read=/path flags enforce a fixed allowlist at startup and cannot adapt to runtime decisions.
--allow-read implements a deny‑by‑default posture that is immutable for the process lifetime.Deno.permissions.query({ name: "read", path: "..." }) returns the current permission state without prompting.Deno.permissions.request({ name: "read", path: "..." }) triggers a user prompt (in interactive terminals) and can expand the allowlist at runtime.PermissionDeniedError.Static flags give stronger guarantees because the OS‑level sandbox is configured before any user code runs. Runtime queries shift the responsibility to application logic, which increases flexibility but also the surface for bugs. On Windows, path normalization differences (e.g., drive letters, case‑insensitivity) can cause a path that passes a flag check to resolve outside the intended directory; Unix‑like systems are generally stricter but symlinks can still bypass restrictions if not resolved.
--allow-read paths that are always required (e.g., application config directory).Deno.permissions.query() to see if access is already granted.Deno.permissions.request() and handle the returned PermissionStatus.try/catch for Deno.errors.PermissionDenied and provide a user‑friendly fallback.# 1. Static enforcement test
deno run --allow-read=/tmp test_read.ts
# test_read.ts attempts to read /etc/passwd – should fail
# 2. Query current permission
deno run --allow-read=/tmp query_test.ts
# query_test.ts: console.log(await Deno.permissions.query({name:"read", path:"/tmp"}))
# 3. Interactive request test (requires a TTY)
deno run request_test.ts
# request_test.ts: const status = await Deno.permissions.request({name:"read", path:"/home/user/docs"});
# Observe the prompt and result
Does your application run in an interactive terminal where user prompts are feasible? If the answer is no (e.g., a CI pipeline, a server daemon, or a compiled binary), Deno.permissions.request() will always resolve to "denied" without user interaction, making static flags the only reliable option.
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 01 Aug 2021, 23:40 UTC
A Deno.permissions.request({ path: "/etc/passwd" }) call cannot grant read access to a path omitted from the startup --allow-read= whitelist. The query only evaluates whether the process already holds that permission; it does not prompt the OS or user to add a new directory at runtime. If your application needs conditional directory access based on config or user input, build the whitelist before launch—for example from an environment variable—or gate file operations behind an application-level allow list rather than expecting permissions.request() to broaden scope.
Practical check: start with --allow-read=/tmp, then call Deno.permissions.request({ path: "/etc/passwd" }); the request should resolve to denied, not grant access.