Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a737159
feat: denied env vars to none
dsherret Nov 4, 2025
9a755aa
update
dsherret Nov 4, 2025
8858b66
update set and delete
dsherret Nov 4, 2025
b706ffd
fix
dsherret Nov 4, 2025
83c98fc
better
dsherret Nov 4, 2025
be118da
Merge branch 'main' into feat_allow_env_deny_to_none
dsherret Nov 5, 2025
ffc2506
small fixes
dsherret Nov 5, 2025
efacd4d
update
dsherret Nov 5, 2025
f6ddea8
add partial denied
dsherret Nov 5, 2025
f9f9e71
add partial denied
dsherret Nov 5, 2025
e88b7dd
fix
dsherret Nov 5, 2025
511c88c
update
dsherret Nov 6, 2025
09e3e81
remove allocation
dsherret Nov 6, 2025
33b3ed4
Merge branch 'main' into feat_allow_env_deny_to_none
dsherret Nov 6, 2025
21f51a3
fix logic for deny
dsherret Nov 6, 2025
b8f33e7
fix logic for deny
dsherret Nov 6, 2025
cd23acc
Update cli/schemas/config-file.v1.json
dsherret Nov 6, 2025
75f2a00
fixes
dsherret Nov 6, 2025
db08877
fix bug in permissions
dsherret Nov 7, 2025
db6881b
fix build error
dsherret Nov 7, 2025
5bd064f
fix another issue
dsherret Nov 7, 2025
1cb5f7c
saving work
dsherret Nov 7, 2025
499b691
adding single descriptors collection
dsherret Nov 7, 2025
b8affe1
working
dsherret Nov 7, 2025
b13d975
use a vec
dsherret Nov 7, 2025
dd6de11
add test for env prefix
dsherret Nov 7, 2025
f296335
more tests
dsherret Nov 7, 2025
f658c29
make more internals private of descriptors
dsherret Nov 7, 2025
efce3fb
Merge branch 'main' into feat_allow_env_deny_to_none
dsherret Nov 13, 2025
446516f
fixes
dsherret Nov 13, 2025
3159ff5
update
dsherret Nov 13, 2025
5666ad5
Merge branch 'main' into feat_allow_env_deny_to_none
dsherret Nov 14, 2025
6d9ec0a
Merge branch 'main' into feat_allow_env_deny_to_none
dsherret Nov 19, 2025
630caf7
review
dsherret Nov 19, 2025
2460399
switch to object variant
dsherret Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 88 additions & 27 deletions cli/args/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ pub struct PermissionFlags {
pub allow_all: bool,
pub allow_env: Option<Vec<String>>,
pub deny_env: Option<Vec<String>>,
pub ignore_env: Option<Vec<String>>,
pub allow_ffi: Option<Vec<String>>,
pub deny_ffi: Option<Vec<String>>,
pub allow_net: Option<Vec<String>>,
Expand All @@ -836,6 +837,7 @@ impl PermissionFlags {
self.allow_all
|| self.allow_env.is_some()
|| self.deny_env.is_some()
|| self.ignore_env.is_some()
|| self.allow_ffi.is_some()
|| self.deny_ffi.is_some()
|| self.allow_net.is_some()
Expand Down Expand Up @@ -974,6 +976,17 @@ impl Flags {
_ => {}
}

match &self.permissions.ignore_env {
Some(env_ignorelist) if env_ignorelist.is_empty() => {
args.push("--ignore-env".to_string());
}
Some(env_ignorelist) => {
let s = format!("--ignore-env={}", env_ignorelist.join(","));
args.push(s);
}
_ => {}
}

match &self.permissions.allow_run {
Some(run_allowlist) if run_allowlist.is_empty() => {
args.push("--allow-run".to_string());
Expand Down Expand Up @@ -4163,6 +4176,30 @@ fn compile_args_without_check_args(app: Command) -> Command {
}

fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
let make_deny_ignore_env_arg = |arg: Arg| {
let mut arg = arg
.num_args(0..)
.use_value_delimiter(true)
.require_equals(true)
.value_name("VARIABLE_NAME")
.long_help("false")
.value_parser(|key: &str| {
if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
return Err(format!("invalid key \"{key}\""));
}

Ok(if cfg!(windows) {
key.to_uppercase()
} else {
key.to_string()
})
})
.hide(true);
if let Some(requires) = requires {
arg = arg.requires(requires)
}
arg
};
app
.after_help(cstr!(r#"<y>Permission options:</>
<y>Docs</>: <c>https://docs.deno.com/go/permissions</>
Expand Down Expand Up @@ -4367,33 +4404,8 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
arg
}
)
.arg(
{
let mut arg = Arg::new("deny-env")
.long("deny-env")
.num_args(0..)
.use_value_delimiter(true)
.require_equals(true)
.value_name("VARIABLE_NAME")
.long_help("false")
.value_parser(|key: &str| {
if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
return Err(format!("invalid key \"{key}\""));
}

Ok(if cfg!(windows) {
key.to_uppercase()
} else {
key.to_string()
})
})
.hide(true);
if let Some(requires) = requires {
arg = arg.requires(requires)
}
arg
}
)
.arg(make_deny_ignore_env_arg(Arg::new("deny-env").long("deny-env")))
.arg(make_deny_ignore_env_arg(Arg::new("ignore-env").long("ignore-env")))
.arg(
{
let mut arg = Arg::new("allow-sys")
Expand Down Expand Up @@ -6624,6 +6636,11 @@ fn permission_args_parse(
debug!("env denylist: {:#?}", &flags.permissions.deny_env);
}

if let Some(env_wl) = matches.remove_many::<String>("ignore-env") {
flags.permissions.ignore_env = Some(env_wl.collect());
debug!("env ignorelist: {:#?}", &flags.permissions.ignore_env);
}

if let Some(run_wl) = matches.remove_many::<String>("allow-run") {
flags.permissions.allow_run = Some(run_wl.collect());
debug!("run allowlist: {:#?}", &flags.permissions.allow_run);
Expand Down Expand Up @@ -9208,6 +9225,26 @@ mod tests {
);
}

#[test]
fn ignore_env_ignorelist() {
let r =
flags_from_vec(svec!["deno", "run", "--ignore-env=HOME", "script.ts"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Run(RunFlags::new_default(
"script.ts".to_string(),
)),
permissions: PermissionFlags {
ignore_env: Some(svec!["HOME"]),
..Default::default()
},
code_cache_enabled: true,
..Flags::default()
}
);
}

#[test]
fn allow_env_allowlist_multiple() {
let r = flags_from_vec(svec![
Expand Down Expand Up @@ -9252,6 +9289,30 @@ mod tests {
);
}

#[test]
fn deny_env_ignorelist_multiple() {
let r = flags_from_vec(svec![
"deno",
"run",
"--ignore-env=HOME,PATH",
"script.ts"
]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Run(RunFlags::new_default(
"script.ts".to_string(),
)),
permissions: PermissionFlags {
ignore_env: Some(svec!["HOME", "PATH"]),
..Default::default()
},
code_cache_enabled: true,
..Flags::default()
}
);
}

#[test]
fn allow_env_allowlist_validator() {
let r =
Expand Down
31 changes: 21 additions & 10 deletions cli/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1546,7 +1546,7 @@ fn flags_to_permissions_options(
}
}

fn handle_deny(
fn handle_deny_or_ignore(
value: Option<&Vec<String>>,
config: Option<&PermissionConfigValue>,
parse_config_value: &impl Fn(&str) -> String,
Expand Down Expand Up @@ -1616,19 +1616,24 @@ fn flags_to_permissions_options(
config.and_then(|c| c.permissions.env.allow.as_ref()),
&identity,
),
deny_env: handle_deny(
deny_env: handle_deny_or_ignore(
flags.deny_env.as_ref(),
config.and_then(|c| c.permissions.env.deny.as_ref()),
&identity,
),
ignore_env: handle_deny_or_ignore(
flags.ignore_env.as_ref(),
config.and_then(|c| c.permissions.env.ignore.as_ref()),
&identity,
),
allow_net: handle_allow(
flags.allow_all,
config.and_then(|c| c.permissions.all),
flags.allow_net.as_ref(),
config.and_then(|c| c.permissions.net.allow.as_ref()),
&identity,
),
deny_net: handle_deny(
deny_net: handle_deny_or_ignore(
flags.deny_net.as_ref(),
config.and_then(|c| c.permissions.net.deny.as_ref()),
&identity,
Expand All @@ -1640,7 +1645,7 @@ fn flags_to_permissions_options(
config.and_then(|c| c.permissions.ffi.allow.as_ref()),
&make_fs_config_value_absolute,
),
deny_ffi: handle_deny(
deny_ffi: handle_deny_or_ignore(
flags.deny_ffi.as_ref(),
config.and_then(|c| c.permissions.ffi.deny.as_ref()),
&make_fs_config_value_absolute,
Expand All @@ -1652,7 +1657,7 @@ fn flags_to_permissions_options(
config.and_then(|c| c.permissions.read.allow.as_ref()),
&make_fs_config_value_absolute,
),
deny_read: handle_deny(
deny_read: handle_deny_or_ignore(
flags.deny_read.as_ref(),
config.and_then(|c| c.permissions.read.deny.as_ref()),
&make_fs_config_value_absolute,
Expand All @@ -1664,7 +1669,7 @@ fn flags_to_permissions_options(
config.and_then(|c| c.permissions.run.allow.as_ref()),
&make_run_config_value_absolute,
),
deny_run: handle_deny(
deny_run: handle_deny_or_ignore(
flags.deny_run.as_ref(),
config.and_then(|c| c.permissions.run.deny.as_ref()),
&make_run_config_value_absolute,
Expand All @@ -1676,7 +1681,7 @@ fn flags_to_permissions_options(
config.and_then(|c| c.permissions.sys.allow.as_ref()),
&identity,
),
deny_sys: handle_deny(
deny_sys: handle_deny_or_ignore(
flags.deny_sys.as_ref(),
config.and_then(|c| c.permissions.sys.deny.as_ref()),
&identity,
Expand All @@ -1688,7 +1693,7 @@ fn flags_to_permissions_options(
config.and_then(|c| c.permissions.write.allow.as_ref()),
&make_fs_config_value_absolute,
),
deny_write: handle_deny(
deny_write: handle_deny_or_ignore(
flags.deny_write.as_ref(),
config.and_then(|c| c.permissions.write.deny.as_ref()),
&make_fs_config_value_absolute,
Expand All @@ -1700,7 +1705,7 @@ fn flags_to_permissions_options(
config.and_then(|c| c.permissions.import.allow.as_ref()),
&identity,
),
deny_import: handle_deny(
deny_import: handle_deny_or_ignore(
flags.deny_import.as_ref(),
config.and_then(|c| c.permissions.import.deny.as_ref()),
&identity,
Expand All @@ -1711,6 +1716,7 @@ fn flags_to_permissions_options(

#[cfg(test)]
mod test {
use deno_config::deno_json::AllowDenyIgnorePermissionConfig;
use deno_config::deno_json::AllowDenyPermissionConfig;
use deno_config::deno_json::PermissionsObject;
use pretty_assertions::assert_eq;
Expand Down Expand Up @@ -1823,13 +1829,16 @@ mod test {
"example.com".to_string(),
])),
},
env: AllowDenyPermissionConfig {
env: AllowDenyIgnorePermissionConfig {
allow: Some(PermissionConfigValue::Some(vec![
"env-allow".to_string(),
])),
deny: Some(PermissionConfigValue::Some(vec![
"env-deny".to_string(),
])),
ignore: Some(PermissionConfigValue::Some(vec![
"env-ignore".to_string(),
])),
},
net: AllowDenyPermissionConfig {
allow: Some(PermissionConfigValue::Some(vec![
Expand Down Expand Up @@ -1874,6 +1883,7 @@ mod test {
PermissionsOptions {
allow_env: Some(vec!["env-allow".to_string()]),
deny_env: Some(vec!["env-deny".to_string()]),
ignore_env: Some(vec!["env-ignore".to_string()]),
allow_net: Some(vec!["net-allow".to_string()]),
deny_net: Some(vec!["net-deny".to_string()]),
allow_ffi: Some(vec![
Expand Down Expand Up @@ -1973,6 +1983,7 @@ mod test {
PermissionsOptions {
allow_env: Some(vec![]),
deny_env: None,
ignore_env: None,
allow_net: Some(vec![]),
deny_net: None,
allow_ffi: Some(vec![]),
Expand Down
19 changes: 18 additions & 1 deletion cli/schemas/config-file.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@
"items": { "type": "string" }
}]
},
"allowDenyIgnorePermissionConfig": {
"type": "object",
"description": "Object form to allow, deny, and/or ignore permissions.",
"additionalProperties": false,
"properties": {
"allow": { "$ref": "#/$defs/permissionConfigValue" },
"deny": { "$ref": "#/$defs/permissionConfigValue" },
"ignore": { "$ref": "#/$defs/permissionConfigValue" }
}
},
"allowDenyIgnorePermissionConfigValue": {
"oneOf": [{
"$ref": "#/$defs/permissionConfigValue"
}, {
"$ref": "#/$defs/allowDenyIgnorePermissionConfig"
}]
},
"allowDenyPermissionConfig": {
"type": "object",
"description": "Object form to allow and/or deny permissions.",
Expand Down Expand Up @@ -52,7 +69,7 @@
"read": { "$ref": "#/$defs/allowDenyPermissionConfigValue" },
"write": { "$ref": "#/$defs/allowDenyPermissionConfigValue" },
"import": { "$ref": "#/$defs/allowDenyPermissionConfigValue" },
"env": { "$ref": "#/$defs/allowDenyPermissionConfigValue" },
"env": { "$ref": "#/$defs/allowDenyIgnorePermissionConfigValue" },
"net": { "$ref": "#/$defs/allowDenyPermissionConfigValue" },
"run": { "$ref": "#/$defs/allowDenyPermissionConfigValue" },
"ffi": { "$ref": "#/$defs/allowDenyPermissionConfigValue" },
Expand Down
Loading
Loading