1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

fix(regression): do not expose resolved path in Deno.Command permission denied error (#25434)

Regression from https://github.com/denoland/deno/pull/25370
This commit is contained in:
David Sherret 2024-09-05 00:57:49 +02:00 committed by GitHub
parent 195b17ae12
commit dd208a6df0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 99 additions and 21 deletions

View file

@ -17,6 +17,7 @@ use deno_io::ChildStderrResource;
use deno_io::ChildStdinResource; use deno_io::ChildStdinResource;
use deno_io::ChildStdoutResource; use deno_io::ChildStdoutResource;
use deno_permissions::PermissionsContainer; use deno_permissions::PermissionsContainer;
use deno_permissions::RunPathQuery;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use std::borrow::Cow; use std::borrow::Cow;
@ -516,7 +517,15 @@ fn compute_run_cmd_and_check_permissions(
.with_context(|| format!("Failed to spawn '{}'", arg_cmd))?; .with_context(|| format!("Failed to spawn '{}'", arg_cmd))?;
let cmd = resolve_cmd(arg_cmd, &run_env) let cmd = resolve_cmd(arg_cmd, &run_env)
.with_context(|| format!("Failed to spawn '{}'", arg_cmd))?; .with_context(|| format!("Failed to spawn '{}'", arg_cmd))?;
check_run_permission(state, &cmd, &run_env, api_name)?; check_run_permission(
state,
RunPathQuery {
requested: arg_cmd,
resolved: &cmd,
},
&run_env,
api_name,
)?;
Ok((cmd, run_env)) Ok((cmd, run_env))
} }
@ -588,7 +597,7 @@ fn resolve_path(path: &str, cwd: &Path) -> PathBuf {
fn check_run_permission( fn check_run_permission(
state: &mut OpState, state: &mut OpState,
cmd: &Path, cmd: RunPathQuery,
run_env: &RunEnv, run_env: &RunEnv,
api_name: &str, api_name: &str,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {

View file

@ -862,6 +862,12 @@ impl AsRef<str> for EnvDescriptor {
} }
} }
#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
pub struct RunPathQuery<'a> {
pub requested: &'a str,
pub resolved: &'a Path,
}
pub enum RunDescriptorArg { pub enum RunDescriptorArg {
Name(String), Name(String),
Path(PathBuf), Path(PathBuf),
@ -1321,16 +1327,16 @@ impl UnaryPermission<RunDescriptor> {
pub fn check( pub fn check(
&mut self, &mut self,
cmd: &Path, cmd: RunPathQuery,
api_name: Option<&str>, api_name: Option<&str>,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
debug_assert!(cmd.is_absolute()); debug_assert!(cmd.resolved.is_absolute());
skip_check_if_is_permission_fully_granted!(self); skip_check_if_is_permission_fully_granted!(self);
self.check_desc( self.check_desc(
Some(&RunDescriptor::Path(cmd.to_path_buf())), Some(&RunDescriptor::Path(cmd.resolved.to_path_buf())),
false, false,
api_name, api_name,
|| Some(format!("\"{}\"", cmd.display())), || Some(format!("\"{}\"", cmd.requested)),
) )
} }
@ -1692,7 +1698,7 @@ impl PermissionsContainer {
#[inline(always)] #[inline(always)]
pub fn check_run( pub fn check_run(
&mut self, &mut self,
cmd: &Path, cmd: RunPathQuery,
api_name: &str, api_name: &str,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
self.0.lock().run.check(cmd, Some(api_name)) self.0.lock().run.check(cmd, Some(api_name))
@ -3036,10 +3042,37 @@ mod tests {
#[allow(clippy::disallowed_methods)] #[allow(clippy::disallowed_methods)]
let cwd = std::env::current_dir().unwrap(); let cwd = std::env::current_dir().unwrap();
prompt_value.set(true); prompt_value.set(true);
assert!(perms.run.check(&cwd.join("cat"), None).is_ok()); assert!(perms
.run
.check(
RunPathQuery {
requested: "cat",
resolved: &cwd.join("cat")
},
None
)
.is_ok());
prompt_value.set(false); prompt_value.set(false);
assert!(perms.run.check(&cwd.join("cat"), None).is_ok()); assert!(perms
assert!(perms.run.check(&cwd.join("ls"), None).is_err()); .run
.check(
RunPathQuery {
requested: "cat",
resolved: &cwd.join("cat")
},
None
)
.is_ok());
assert!(perms
.run
.check(
RunPathQuery {
requested: "ls",
resolved: &cwd.join("ls")
},
None
)
.is_err());
prompt_value.set(true); prompt_value.set(true);
assert!(perms.env.check("HOME", None).is_ok()); assert!(perms.env.check("HOME", None).is_ok());
@ -3133,12 +3166,48 @@ mod tests {
prompt_value.set(false); prompt_value.set(false);
#[allow(clippy::disallowed_methods)] #[allow(clippy::disallowed_methods)]
let cwd = std::env::current_dir().unwrap(); let cwd = std::env::current_dir().unwrap();
assert!(perms.run.check(&cwd.join("cat"), None).is_err()); assert!(perms
.run
.check(
RunPathQuery {
requested: "cat",
resolved: &cwd.join("cat")
},
None
)
.is_err());
prompt_value.set(true); prompt_value.set(true);
assert!(perms.run.check(&cwd.join("cat"), None).is_err()); assert!(perms
assert!(perms.run.check(&cwd.join("ls"), None).is_ok()); .run
.check(
RunPathQuery {
requested: "cat",
resolved: &cwd.join("cat")
},
None
)
.is_err());
assert!(perms
.run
.check(
RunPathQuery {
requested: "ls",
resolved: &cwd.join("ls")
},
None
)
.is_ok());
prompt_value.set(false); prompt_value.set(false);
assert!(perms.run.check(&cwd.join("ls"), None).is_ok()); assert!(perms
.run
.check(
RunPathQuery {
requested: "ls",
resolved: &cwd.join("ls")
},
None
)
.is_ok());
prompt_value.set(false); prompt_value.set(false);
assert!(perms.env.check("HOME", None).is_err()); assert!(perms.env.check("HOME", None).is_err());

View file

@ -1,2 +1,2 @@
error: Uncaught (in promise) PermissionDenied: Requires run access to "[WILDLINE]deno[WILDLINE]", specify the required permissions during compilation using `deno compile --allow-run` error: Uncaught (in promise) PermissionDenied: Requires run access to "deno", specify the required permissions during compilation using `deno compile --allow-run`
[WILDCARD] [WILDCARD]

View file

@ -1,10 +1,10 @@
Running... Running...
PermissionDenied: Requires run access to "[WILDLINE]deno[WILDLINE]", run again with the --allow-run flag PermissionDenied: Requires run access to "deno", run again with the --allow-run flag
[WILDCARD] [WILDCARD]
at file:///[WILDLINE]/sub.ts:15:5 { at file:///[WILDLINE]/sub.ts:15:5 {
name: "PermissionDenied" name: "PermissionDenied"
} }
PermissionDenied: Requires run access to "[WILDLINE]deno[WILDLINE]", run again with the --allow-run flag PermissionDenied: Requires run access to "deno", run again with the --allow-run flag
[WILDCARD] [WILDCARD]
at file:///[WILDLINE]/sub.ts:23:22 { at file:///[WILDLINE]/sub.ts:23:22 {
name: "PermissionDenied" name: "PermissionDenied"

View file

@ -9,7 +9,7 @@ new Deno.Command(
"run", "run",
"--allow-write", "--allow-write",
"--allow-read", "--allow-read",
`--allow-run=${binaryName}`, `--allow-run=deno`,
"sub.ts", "sub.ts",
], ],
stderr: "inherit", stderr: "inherit",

View file

@ -6,7 +6,7 @@ Deno.copyFileSync(binaryName, "subdir/" + binaryName);
try { try {
const commandResult = new Deno.Command( const commandResult = new Deno.Command(
binaryName, "deno",
{ {
env: { "PATH": Deno.cwd() + pathSep + "subdir" }, env: { "PATH": Deno.cwd() + pathSep + "subdir" },
stdout: "inherit", stdout: "inherit",
@ -22,7 +22,7 @@ try {
try { try {
const child = Deno.run( const child = Deno.run(
{ {
cmd: [binaryName], cmd: ["deno"],
env: { "PATH": Deno.cwd() + pathSep + "subdir" }, env: { "PATH": Deno.cwd() + pathSep + "subdir" },
stdout: "inherit", stdout: "inherit",
stderr: "inherit", stderr: "inherit",

View file

@ -1,3 +1,3 @@
[WILDCARD]PermissionDenied: Requires run access to "[WILDLINE]ls[WILDLINE]", run again with the --allow-run flag [WILDCARD]PermissionDenied: Requires run access to "ls", run again with the --allow-run flag
[WILDCARD] [WILDCARD]
true true