diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2024-08-28 21:11:37 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-28 21:11:37 -0400 |
commit | c6793f52b9a636b7df130d22b6e87e846245885d (patch) | |
tree | 83810f8e4a8a338f3f8a76892bfe3be3e53de107 /runtime/ops | |
parent | 2afbc1aa39c37b688ea1e0c47161c2fcdefc05ab (diff) |
fix(permissions): disallow any `LD_` or `DYLD_` prefixed env var without full --allow-run permissions (#25271)
Follow up to https://github.com/denoland/deno/pull/25221
I looked into what the list was and it was quite extensive, so I think
as suggested in
https://github.com/denoland/deno/issues/11964#issuecomment-2314585135 we
should disallow this for any `LD_` prefixed env var.
Diffstat (limited to 'runtime/ops')
-rw-r--r-- | runtime/ops/process.rs | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs index 564092454..25edfe662 100644 --- a/runtime/ops/process.rs +++ b/runtime/ops/process.rs @@ -229,21 +229,59 @@ fn create_command( mut args: SpawnArgs, api_name: &str, ) -> Result<CreateCommand, AnyError> { + fn get_requires_allow_all_env_var(args: &SpawnArgs) -> Option<Cow<str>> { + fn requires_allow_all(key: &str) -> bool { + let key = key.trim(); + // we could be more targted here, but there are quite a lot of + // LD_* and DYLD_* env variables + key.starts_with("LD_") || key.starts_with("DYLD_") + } + + /// Checks if the user set this env var to an empty + /// string in order to clear it. + fn args_has_empty_env_value(args: &SpawnArgs, key_name: &str) -> bool { + args + .env + .iter() + .find(|(k, _)| k == key_name) + .map(|(_, v)| v.trim().is_empty()) + .unwrap_or(false) + } + + if let Some((key, _)) = args + .env + .iter() + .find(|(k, v)| requires_allow_all(k) && !v.trim().is_empty()) + { + return Some(key.into()); + } + + if !args.clear_env { + if let Some((key, _)) = std::env::vars().find(|(k, v)| { + requires_allow_all(k) + && !v.trim().is_empty() + && !args_has_empty_env_value(args, k) + }) { + return Some(key.into()); + } + } + + None + } + { let permissions = state.borrow_mut::<PermissionsContainer>(); permissions.check_run(&args.cmd, api_name)?; - // error the same on all platforms - if permissions.check_run_all(api_name).is_err() - && (args.env.iter().any(|(k, _)| k.trim() == "LD_PRELOAD") - || !args.clear_env - && std::env::vars().any(|(k, _)| k.trim() == "LD_PRELOAD")) - { - // we don't allow users to launch subprocesses with the LD_PRELOAD - // env var set because this allows executing any code - return Err(deno_core::error::custom_error( + if permissions.check_run_all(api_name).is_err() { + // error the same on all platforms + if let Some(name) = get_requires_allow_all_env_var(&args) { + // we don't allow users to launch subprocesses with any LD_ or DYLD_* + // env vars set because this allows executing code (ex. LD_PRELOAD) + return Err(deno_core::error::custom_error( "PermissionDenied", - "Requires --allow-all permissions to spawn subprocess with LD_PRELOAD environment variable." + format!("Requires --allow-all permissions to spawn subprocess with {} environment variable.", name) )); + } } } |