summaryrefslogtreecommitdiff
path: root/runtime/ops
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-08-28 21:11:37 -0400
committerGitHub <noreply@github.com>2024-08-28 21:11:37 -0400
commitc6793f52b9a636b7df130d22b6e87e846245885d (patch)
tree83810f8e4a8a338f3f8a76892bfe3be3e53de107 /runtime/ops
parent2afbc1aa39c37b688ea1e0c47161c2fcdefc05ab (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.rs58
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)
));
+ }
}
}