mirror of
https://github.com/denoland/deno.git
synced 2025-09-27 04:39:10 +00:00
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.
This commit is contained in:
parent
2afbc1aa39
commit
c6793f52b9
4 changed files with 66 additions and 10 deletions
|
@ -229,21 +229,59 @@ fn create_command(
|
||||||
mut args: SpawnArgs,
|
mut args: SpawnArgs,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<CreateCommand, AnyError> {
|
) -> 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>();
|
let permissions = state.borrow_mut::<PermissionsContainer>();
|
||||||
permissions.check_run(&args.cmd, api_name)?;
|
permissions.check_run(&args.cmd, api_name)?;
|
||||||
// error the same on all platforms
|
if permissions.check_run_all(api_name).is_err() {
|
||||||
if permissions.check_run_all(api_name).is_err()
|
// error the same on all platforms
|
||||||
&& (args.env.iter().any(|(k, _)| k.trim() == "LD_PRELOAD")
|
if let Some(name) = get_requires_allow_all_env_var(&args) {
|
||||||
|| !args.clear_env
|
// we don't allow users to launch subprocesses with any LD_ or DYLD_*
|
||||||
&& std::env::vars().any(|(k, _)| k.trim() == "LD_PRELOAD"))
|
// env vars set because this allows executing code (ex. LD_PRELOAD)
|
||||||
{
|
return Err(deno_core::error::custom_error(
|
||||||
// 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(
|
|
||||||
"PermissionDenied",
|
"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)
|
||||||
));
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -501,6 +501,10 @@ itest!(_088_dynamic_import_already_evaluating {
|
||||||
// TODO(bartlomieju): remove --unstable once Deno.Command is stabilized
|
// TODO(bartlomieju): remove --unstable once Deno.Command is stabilized
|
||||||
itest!(_089_run_allow_list {
|
itest!(_089_run_allow_list {
|
||||||
args: "run --unstable --allow-run=curl run/089_run_allow_list.ts",
|
args: "run --unstable --allow-run=curl run/089_run_allow_list.ts",
|
||||||
|
envs: vec![
|
||||||
|
("LD_LIBRARY_PATH".to_string(), "".to_string()),
|
||||||
|
("DYLD_FALLBACK_LIBRARY_PATH".to_string(), "".to_string())
|
||||||
|
],
|
||||||
output: "run/089_run_allow_list.ts.out",
|
output: "run/089_run_allow_list.ts.out",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3708,6 +3712,10 @@ itest!(test_and_bench_are_noops_in_run {
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
itest!(spawn_kill_permissions {
|
itest!(spawn_kill_permissions {
|
||||||
args: "run --quiet --allow-run=cat spawn_kill_permissions.ts",
|
args: "run --quiet --allow-run=cat spawn_kill_permissions.ts",
|
||||||
|
envs: vec![
|
||||||
|
("LD_LIBRARY_PATH".to_string(), "".to_string()),
|
||||||
|
("DYLD_FALLBACK_LIBRARY_PATH".to_string(), "".to_string())
|
||||||
|
],
|
||||||
output_str: Some(""),
|
output_str: Some(""),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
{
|
{
|
||||||
|
"envs": {
|
||||||
|
"LD_LIBRARY_PATH": "",
|
||||||
|
"LD_PRELOAD": "",
|
||||||
|
"DYLD_FALLBACK_LIBRARY_PATH": ""
|
||||||
|
},
|
||||||
"tests": {
|
"tests": {
|
||||||
"env_arg": {
|
"env_arg": {
|
||||||
"args": "run --allow-run=echo env_arg.ts",
|
"args": "run --allow-run=echo env_arg.ts",
|
||||||
|
|
|
@ -239,6 +239,11 @@ Deno.test(
|
||||||
async function hostnameWithoutOtherNetworkUsages() {
|
async function hostnameWithoutOtherNetworkUsages() {
|
||||||
const { stdout } = await new Deno.Command(Deno.execPath(), {
|
const { stdout } = await new Deno.Command(Deno.execPath(), {
|
||||||
args: ["eval", "-p", "Deno.hostname()"],
|
args: ["eval", "-p", "Deno.hostname()"],
|
||||||
|
env: {
|
||||||
|
LD_PRELOAD: "",
|
||||||
|
LD_LIBRARY_PATH: "",
|
||||||
|
DYLD_FALLBACK_LIBRARY_PATH: "",
|
||||||
|
},
|
||||||
}).output();
|
}).output();
|
||||||
const hostname = new TextDecoder().decode(stdout).trim();
|
const hostname = new TextDecoder().decode(stdout).trim();
|
||||||
assert(hostname.length > 0);
|
assert(hostname.length > 0);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue