mirror of
https://github.com/denoland/deno.git
synced 2025-08-04 10:59:13 +00:00
fix: lock down allow-run permissions more (#25370)
`--allow-run` even with an allow list has essentially been `--allow-all`... this locks it down more. 1. Resolves allow list for `--allow-run=` on startup to an absolute path, then uses these paths when evaluating if a command can execute. Also, adds these paths to `--deny-write` 1. Resolves the environment (cwd and env vars) before evaluating permissions and before executing a command. Then uses this environment to evaluate the permissions and then evaluate the command.
This commit is contained in:
parent
334c842392
commit
74fc66da11
27 changed files with 684 additions and 364 deletions
|
@ -32,7 +32,6 @@ use std::path::PathBuf;
|
|||
use std::str::FromStr;
|
||||
use std::string::ToString;
|
||||
use std::sync::Arc;
|
||||
use which::which;
|
||||
|
||||
pub mod prompter;
|
||||
use prompter::permission_prompt;
|
||||
|
@ -317,7 +316,7 @@ pub trait Descriptor: Eq + Clone + Hash {
|
|||
|
||||
/// Parse this descriptor from a list of Self::Arg, which may have been converted from
|
||||
/// command-line strings.
|
||||
fn parse(list: &Option<Vec<Self::Arg>>) -> Result<HashSet<Self>, AnyError>;
|
||||
fn parse(list: Option<&[Self::Arg]>) -> Result<HashSet<Self>, AnyError>;
|
||||
|
||||
/// Generic check function to check this descriptor against a `UnaryPermission`.
|
||||
fn check_in_permission(
|
||||
|
@ -333,9 +332,6 @@ pub trait Descriptor: Eq + Clone + Hash {
|
|||
fn stronger_than(&self, other: &Self) -> bool {
|
||||
self == other
|
||||
}
|
||||
fn aliases(&self) -> Vec<Self> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
|
@ -423,43 +419,33 @@ impl<T: Descriptor + Hash> UnaryPermission<T> {
|
|||
desc: Option<&T>,
|
||||
allow_partial: AllowPartial,
|
||||
) -> PermissionState {
|
||||
let aliases = desc.map_or(vec![], T::aliases);
|
||||
for desc in [desc]
|
||||
.into_iter()
|
||||
.chain(aliases.iter().map(Some).collect::<Vec<_>>())
|
||||
{
|
||||
let state = if self.is_flag_denied(desc) || self.is_prompt_denied(desc) {
|
||||
PermissionState::Denied
|
||||
} else if self.is_granted(desc) {
|
||||
match allow_partial {
|
||||
AllowPartial::TreatAsGranted => PermissionState::Granted,
|
||||
AllowPartial::TreatAsDenied => {
|
||||
if self.is_partial_flag_denied(desc) {
|
||||
PermissionState::Denied
|
||||
} else {
|
||||
PermissionState::Granted
|
||||
}
|
||||
}
|
||||
AllowPartial::TreatAsPartialGranted => {
|
||||
if self.is_partial_flag_denied(desc) {
|
||||
PermissionState::GrantedPartial
|
||||
} else {
|
||||
PermissionState::Granted
|
||||
}
|
||||
if self.is_flag_denied(desc) || self.is_prompt_denied(desc) {
|
||||
PermissionState::Denied
|
||||
} else if self.is_granted(desc) {
|
||||
match allow_partial {
|
||||
AllowPartial::TreatAsGranted => PermissionState::Granted,
|
||||
AllowPartial::TreatAsDenied => {
|
||||
if self.is_partial_flag_denied(desc) {
|
||||
PermissionState::Denied
|
||||
} else {
|
||||
PermissionState::Granted
|
||||
}
|
||||
}
|
||||
AllowPartial::TreatAsPartialGranted => {
|
||||
if self.is_partial_flag_denied(desc) {
|
||||
PermissionState::GrantedPartial
|
||||
} else {
|
||||
PermissionState::Granted
|
||||
}
|
||||
}
|
||||
} else if matches!(allow_partial, AllowPartial::TreatAsDenied)
|
||||
&& self.is_partial_flag_denied(desc)
|
||||
{
|
||||
PermissionState::Denied
|
||||
} else {
|
||||
PermissionState::Prompt
|
||||
};
|
||||
if state != PermissionState::Prompt {
|
||||
return state;
|
||||
}
|
||||
} else if matches!(allow_partial, AllowPartial::TreatAsDenied)
|
||||
&& self.is_partial_flag_denied(desc)
|
||||
{
|
||||
PermissionState::Denied
|
||||
} else {
|
||||
PermissionState::Prompt
|
||||
}
|
||||
PermissionState::Prompt
|
||||
}
|
||||
|
||||
fn request_desc(
|
||||
|
@ -512,9 +498,6 @@ impl<T: Descriptor + Hash> UnaryPermission<T> {
|
|||
match desc {
|
||||
Some(desc) => {
|
||||
self.granted_list.retain(|v| !v.stronger_than(desc));
|
||||
for alias in desc.aliases() {
|
||||
self.granted_list.retain(|v| !v.stronger_than(&alias));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.granted_global = false;
|
||||
|
@ -582,11 +565,7 @@ impl<T: Descriptor + Hash> UnaryPermission<T> {
|
|||
) {
|
||||
match desc {
|
||||
Some(desc) => {
|
||||
let aliases = desc.aliases();
|
||||
list.insert(desc);
|
||||
for alias in aliases {
|
||||
list.insert(alias);
|
||||
}
|
||||
}
|
||||
None => *list_global = true,
|
||||
}
|
||||
|
@ -612,7 +591,7 @@ impl<T: Descriptor + Hash> UnaryPermission<T> {
|
|||
ChildUnaryPermissionArg::GrantedList(granted_list) => {
|
||||
let granted: Vec<T::Arg> =
|
||||
granted_list.into_iter().map(From::from).collect();
|
||||
perms.granted_list = T::parse(&Some(granted))?;
|
||||
perms.granted_list = T::parse(Some(&granted))?;
|
||||
if !perms
|
||||
.granted_list
|
||||
.iter()
|
||||
|
@ -649,7 +628,7 @@ impl Descriptor for ReadDescriptor {
|
|||
perm.check_desc(Some(self), true, api_name, || None)
|
||||
}
|
||||
|
||||
fn parse(args: &Option<Vec<Self::Arg>>) -> Result<HashSet<Self>, AnyError> {
|
||||
fn parse(args: Option<&[Self::Arg]>) -> Result<HashSet<Self>, AnyError> {
|
||||
parse_path_list(args, ReadDescriptor)
|
||||
}
|
||||
|
||||
|
@ -681,7 +660,7 @@ impl Descriptor for WriteDescriptor {
|
|||
perm.check_desc(Some(self), true, api_name, || None)
|
||||
}
|
||||
|
||||
fn parse(args: &Option<Vec<Self::Arg>>) -> Result<HashSet<Self>, AnyError> {
|
||||
fn parse(args: Option<&[Self::Arg]>) -> Result<HashSet<Self>, AnyError> {
|
||||
parse_path_list(args, WriteDescriptor)
|
||||
}
|
||||
|
||||
|
@ -754,7 +733,7 @@ impl Descriptor for NetDescriptor {
|
|||
perm.check_desc(Some(self), false, api_name, || None)
|
||||
}
|
||||
|
||||
fn parse(args: &Option<Vec<Self::Arg>>) -> Result<HashSet<Self>, AnyError> {
|
||||
fn parse(args: Option<&[Self::Arg]>) -> Result<HashSet<Self>, AnyError> {
|
||||
parse_net_list(args)
|
||||
}
|
||||
|
||||
|
@ -864,7 +843,7 @@ impl Descriptor for EnvDescriptor {
|
|||
perm.check_desc(Some(self), false, api_name, || None)
|
||||
}
|
||||
|
||||
fn parse(list: &Option<Vec<Self::Arg>>) -> Result<HashSet<Self>, AnyError> {
|
||||
fn parse(list: Option<&[Self::Arg]>) -> Result<HashSet<Self>, AnyError> {
|
||||
parse_env_list(list)
|
||||
}
|
||||
|
||||
|
@ -883,6 +862,11 @@ impl AsRef<str> for EnvDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum RunDescriptorArg {
|
||||
Name(String),
|
||||
Path(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub enum RunDescriptor {
|
||||
/// Warning: You may want to construct with `RunDescriptor::from()` for case
|
||||
|
@ -893,8 +877,26 @@ pub enum RunDescriptor {
|
|||
Path(PathBuf),
|
||||
}
|
||||
|
||||
impl From<String> for RunDescriptorArg {
|
||||
fn from(s: String) -> Self {
|
||||
#[cfg(windows)]
|
||||
let s = s.to_lowercase();
|
||||
let is_path = s.contains('/');
|
||||
#[cfg(windows)]
|
||||
let is_path = is_path || s.contains('\\') || Path::new(&s).is_absolute();
|
||||
if is_path {
|
||||
Self::Path(resolve_from_cwd(Path::new(&s)).unwrap())
|
||||
} else {
|
||||
match which::which(&s) {
|
||||
Ok(path) => Self::Path(path),
|
||||
Err(_) => Self::Name(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Descriptor for RunDescriptor {
|
||||
type Arg = String;
|
||||
type Arg = RunDescriptorArg;
|
||||
|
||||
fn check_in_permission(
|
||||
&self,
|
||||
|
@ -905,7 +907,7 @@ impl Descriptor for RunDescriptor {
|
|||
perm.check_desc(Some(self), false, api_name, || None)
|
||||
}
|
||||
|
||||
fn parse(args: &Option<Vec<Self::Arg>>) -> Result<HashSet<Self>, AnyError> {
|
||||
fn parse(args: Option<&[Self::Arg]>) -> Result<HashSet<Self>, AnyError> {
|
||||
parse_run_list(args)
|
||||
}
|
||||
|
||||
|
@ -916,16 +918,6 @@ impl Descriptor for RunDescriptor {
|
|||
fn name(&self) -> Cow<str> {
|
||||
Cow::from(self.to_string())
|
||||
}
|
||||
|
||||
fn aliases(&self) -> Vec<Self> {
|
||||
match self {
|
||||
RunDescriptor::Name(name) => match which(name) {
|
||||
Ok(path) => vec![RunDescriptor::Path(path)],
|
||||
Err(_) => vec![],
|
||||
},
|
||||
RunDescriptor::Path(_) => vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for RunDescriptor {
|
||||
|
@ -938,7 +930,10 @@ impl From<String> for RunDescriptor {
|
|||
if is_path {
|
||||
Self::Path(resolve_from_cwd(Path::new(&s)).unwrap())
|
||||
} else {
|
||||
Self::Name(s)
|
||||
match which::which(&s) {
|
||||
Ok(path) => Self::Path(path),
|
||||
Err(_) => Self::Name(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -947,11 +942,7 @@ impl From<PathBuf> for RunDescriptor {
|
|||
fn from(p: PathBuf) -> Self {
|
||||
#[cfg(windows)]
|
||||
let p = PathBuf::from(p.to_string_lossy().to_string().to_lowercase());
|
||||
if p.is_absolute() {
|
||||
Self::Path(p)
|
||||
} else {
|
||||
Self::Path(resolve_from_cwd(&p).unwrap())
|
||||
}
|
||||
Self::Path(resolve_from_cwd(&p).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -988,7 +979,7 @@ impl Descriptor for SysDescriptor {
|
|||
perm.check_desc(Some(self), false, api_name, || None)
|
||||
}
|
||||
|
||||
fn parse(list: &Option<Vec<Self::Arg>>) -> Result<HashSet<Self>, AnyError> {
|
||||
fn parse(list: Option<&[Self::Arg]>) -> Result<HashSet<Self>, AnyError> {
|
||||
parse_sys_list(list)
|
||||
}
|
||||
|
||||
|
@ -1025,7 +1016,7 @@ impl Descriptor for FfiDescriptor {
|
|||
perm.check_desc(Some(self), true, api_name, || None)
|
||||
}
|
||||
|
||||
fn parse(list: &Option<Vec<Self::Arg>>) -> Result<HashSet<Self>, AnyError> {
|
||||
fn parse(list: Option<&[Self::Arg]>) -> Result<HashSet<Self>, AnyError> {
|
||||
parse_path_list(list, FfiDescriptor)
|
||||
}
|
||||
|
||||
|
@ -1330,15 +1321,16 @@ impl UnaryPermission<RunDescriptor> {
|
|||
|
||||
pub fn check(
|
||||
&mut self,
|
||||
cmd: &str,
|
||||
cmd: &Path,
|
||||
api_name: Option<&str>,
|
||||
) -> Result<(), AnyError> {
|
||||
debug_assert!(cmd.is_absolute());
|
||||
skip_check_if_is_permission_fully_granted!(self);
|
||||
self.check_desc(
|
||||
Some(&RunDescriptor::from(cmd.to_string())),
|
||||
Some(&RunDescriptor::Path(cmd.to_path_buf())),
|
||||
false,
|
||||
api_name,
|
||||
|| Some(format!("\"{}\"", cmd)),
|
||||
|| Some(format!("\"{}\"", cmd.display())),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1346,6 +1338,21 @@ impl UnaryPermission<RunDescriptor> {
|
|||
skip_check_if_is_permission_fully_granted!(self);
|
||||
self.check_desc(None, false, api_name, || None)
|
||||
}
|
||||
|
||||
/// Queries without prompting
|
||||
pub fn query_all(&mut self, api_name: Option<&str>) -> bool {
|
||||
if self.is_allow_all() {
|
||||
return true;
|
||||
}
|
||||
let (result, _prompted, _is_allow_all) =
|
||||
self.query_desc(None, AllowPartial::TreatAsDenied).check2(
|
||||
RunDescriptor::flag_name(),
|
||||
api_name,
|
||||
|| None,
|
||||
/* prompt */ false,
|
||||
);
|
||||
result.is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryPermission<FfiDescriptor> {
|
||||
|
@ -1429,7 +1436,7 @@ pub struct PermissionsOptions {
|
|||
pub deny_ffi: Option<Vec<PathBuf>>,
|
||||
pub allow_read: Option<Vec<PathBuf>>,
|
||||
pub deny_read: Option<Vec<PathBuf>>,
|
||||
pub allow_run: Option<Vec<String>>,
|
||||
pub allow_run: Option<Vec<PathBuf>>,
|
||||
pub deny_run: Option<Vec<String>>,
|
||||
pub allow_sys: Option<Vec<String>>,
|
||||
pub deny_sys: Option<Vec<String>>,
|
||||
|
@ -1440,8 +1447,8 @@ pub struct PermissionsOptions {
|
|||
|
||||
impl Permissions {
|
||||
pub fn new_unary<T>(
|
||||
allow_list: &Option<Vec<T::Arg>>,
|
||||
deny_list: &Option<Vec<T::Arg>>,
|
||||
allow_list: Option<&[T::Arg]>,
|
||||
deny_list: Option<&[T::Arg]>,
|
||||
prompt: bool,
|
||||
) -> Result<UnaryPermission<T>, AnyError>
|
||||
where
|
||||
|
@ -1470,38 +1477,54 @@ impl Permissions {
|
|||
pub fn from_options(opts: &PermissionsOptions) -> Result<Self, AnyError> {
|
||||
Ok(Self {
|
||||
read: Permissions::new_unary(
|
||||
&opts.allow_read,
|
||||
&opts.deny_read,
|
||||
opts.allow_read.as_deref(),
|
||||
opts.deny_read.as_deref(),
|
||||
opts.prompt,
|
||||
)?,
|
||||
write: Permissions::new_unary(
|
||||
&opts.allow_write,
|
||||
&opts.deny_write,
|
||||
opts.allow_write.as_deref(),
|
||||
opts.deny_write.as_deref(),
|
||||
opts.prompt,
|
||||
)?,
|
||||
net: Permissions::new_unary(
|
||||
&opts.allow_net,
|
||||
&opts.deny_net,
|
||||
opts.allow_net.as_deref(),
|
||||
opts.deny_net.as_deref(),
|
||||
opts.prompt,
|
||||
)?,
|
||||
env: Permissions::new_unary(
|
||||
&opts.allow_env,
|
||||
&opts.deny_env,
|
||||
opts.allow_env.as_deref(),
|
||||
opts.deny_env.as_deref(),
|
||||
opts.prompt,
|
||||
)?,
|
||||
sys: Permissions::new_unary(
|
||||
&opts.allow_sys,
|
||||
&opts.deny_sys,
|
||||
opts.allow_sys.as_deref(),
|
||||
opts.deny_sys.as_deref(),
|
||||
opts.prompt,
|
||||
)?,
|
||||
run: Permissions::new_unary(
|
||||
&opts.allow_run,
|
||||
&opts.deny_run,
|
||||
opts
|
||||
.allow_run
|
||||
.as_ref()
|
||||
.map(|d| {
|
||||
d.iter()
|
||||
.map(|s| RunDescriptorArg::Path(s.clone()))
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.as_deref(),
|
||||
opts
|
||||
.deny_run
|
||||
.as_ref()
|
||||
.map(|d| {
|
||||
d.iter()
|
||||
.map(|s| RunDescriptorArg::from(s.clone()))
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.as_deref(),
|
||||
opts.prompt,
|
||||
)?,
|
||||
ffi: Permissions::new_unary(
|
||||
&opts.allow_ffi,
|
||||
&opts.deny_ffi,
|
||||
opts.allow_ffi.as_deref(),
|
||||
opts.deny_ffi.as_deref(),
|
||||
opts.prompt,
|
||||
)?,
|
||||
all: Permissions::new_all(opts.allow_all),
|
||||
|
@ -1534,13 +1557,13 @@ impl Permissions {
|
|||
|
||||
fn none(prompt: bool) -> Self {
|
||||
Self {
|
||||
read: Permissions::new_unary(&None, &None, prompt).unwrap(),
|
||||
write: Permissions::new_unary(&None, &None, prompt).unwrap(),
|
||||
net: Permissions::new_unary(&None, &None, prompt).unwrap(),
|
||||
env: Permissions::new_unary(&None, &None, prompt).unwrap(),
|
||||
sys: Permissions::new_unary(&None, &None, prompt).unwrap(),
|
||||
run: Permissions::new_unary(&None, &None, prompt).unwrap(),
|
||||
ffi: Permissions::new_unary(&None, &None, prompt).unwrap(),
|
||||
read: Permissions::new_unary(None, None, prompt).unwrap(),
|
||||
write: Permissions::new_unary(None, None, prompt).unwrap(),
|
||||
net: Permissions::new_unary(None, None, prompt).unwrap(),
|
||||
env: Permissions::new_unary(None, None, prompt).unwrap(),
|
||||
sys: Permissions::new_unary(None, None, prompt).unwrap(),
|
||||
run: Permissions::new_unary(None, None, prompt).unwrap(),
|
||||
ffi: Permissions::new_unary(None, None, prompt).unwrap(),
|
||||
all: Permissions::new_all(false),
|
||||
}
|
||||
}
|
||||
|
@ -1669,7 +1692,7 @@ impl PermissionsContainer {
|
|||
#[inline(always)]
|
||||
pub fn check_run(
|
||||
&mut self,
|
||||
cmd: &str,
|
||||
cmd: &Path,
|
||||
api_name: &str,
|
||||
) -> Result<(), AnyError> {
|
||||
self.0.lock().run.check(cmd, Some(api_name))
|
||||
|
@ -1680,6 +1703,11 @@ impl PermissionsContainer {
|
|||
self.0.lock().run.check_all(Some(api_name))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn query_run_all(&mut self, api_name: &str) -> bool {
|
||||
self.0.lock().run.query_all(Some(api_name))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> {
|
||||
self.0.lock().sys.check(kind, Some(api_name))
|
||||
|
@ -1871,12 +1899,12 @@ const fn unit_permission_from_flag_bools(
|
|||
}
|
||||
}
|
||||
|
||||
fn global_from_option<T>(flag: &Option<Vec<T>>) -> bool {
|
||||
fn global_from_option<T>(flag: Option<&[T]>) -> bool {
|
||||
matches!(flag, Some(v) if v.is_empty())
|
||||
}
|
||||
|
||||
fn parse_net_list(
|
||||
list: &Option<Vec<String>>,
|
||||
list: Option<&[String]>,
|
||||
) -> Result<HashSet<NetDescriptor>, AnyError> {
|
||||
if let Some(v) = list {
|
||||
v.iter()
|
||||
|
@ -1888,7 +1916,7 @@ fn parse_net_list(
|
|||
}
|
||||
|
||||
fn parse_env_list(
|
||||
list: &Option<Vec<String>>,
|
||||
list: Option<&[String]>,
|
||||
) -> Result<HashSet<EnvDescriptor>, AnyError> {
|
||||
if let Some(v) = list {
|
||||
v.iter()
|
||||
|
@ -1906,7 +1934,7 @@ fn parse_env_list(
|
|||
}
|
||||
|
||||
fn parse_path_list<T: Descriptor + Hash>(
|
||||
list: &Option<Vec<PathBuf>>,
|
||||
list: Option<&[PathBuf]>,
|
||||
f: fn(PathBuf) -> T,
|
||||
) -> Result<HashSet<T>, AnyError> {
|
||||
if let Some(v) = list {
|
||||
|
@ -1925,7 +1953,7 @@ fn parse_path_list<T: Descriptor + Hash>(
|
|||
}
|
||||
|
||||
fn parse_sys_list(
|
||||
list: &Option<Vec<String>>,
|
||||
list: Option<&[String]>,
|
||||
) -> Result<HashSet<SysDescriptor>, AnyError> {
|
||||
if let Some(v) = list {
|
||||
v.iter()
|
||||
|
@ -1943,22 +1971,19 @@ fn parse_sys_list(
|
|||
}
|
||||
|
||||
fn parse_run_list(
|
||||
list: &Option<Vec<String>>,
|
||||
list: Option<&[RunDescriptorArg]>,
|
||||
) -> Result<HashSet<RunDescriptor>, AnyError> {
|
||||
let mut result = HashSet::new();
|
||||
if let Some(v) = list {
|
||||
for s in v {
|
||||
if s.is_empty() {
|
||||
return Err(AnyError::msg("Empty path is not allowed"));
|
||||
} else {
|
||||
let desc = RunDescriptor::from(s.to_string());
|
||||
let aliases = desc.aliases();
|
||||
result.insert(desc);
|
||||
result.extend(aliases);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
let Some(v) = list else {
|
||||
return Ok(HashSet::new());
|
||||
};
|
||||
Ok(
|
||||
v.iter()
|
||||
.map(|arg| match arg {
|
||||
RunDescriptorArg::Name(s) => RunDescriptor::Name(s.clone()),
|
||||
RunDescriptorArg::Path(l) => RunDescriptor::Path(l.clone()),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn escalation_error() -> AnyError {
|
||||
|
@ -2298,6 +2323,9 @@ mod tests {
|
|||
macro_rules! svec {
|
||||
($($x:expr),*) => (vec![$($x.to_string()),*]);
|
||||
}
|
||||
macro_rules! sarr {
|
||||
($($x:expr),*) => ([$($x.to_string()),*]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_paths() {
|
||||
|
@ -2678,94 +2706,88 @@ mod tests {
|
|||
set_prompter(Box::new(TestPrompter));
|
||||
let perms1 = Permissions::allow_all();
|
||||
let perms2 = Permissions {
|
||||
read: Permissions::new_unary(
|
||||
&Some(vec![PathBuf::from("/foo")]),
|
||||
&None,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
read: Permissions::new_unary(Some(&[PathBuf::from("/foo")]), None, false)
|
||||
.unwrap(),
|
||||
write: Permissions::new_unary(
|
||||
&Some(vec![PathBuf::from("/foo")]),
|
||||
&None,
|
||||
Some(&[PathBuf::from("/foo")]),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
ffi: Permissions::new_unary(
|
||||
&Some(vec![PathBuf::from("/foo")]),
|
||||
&None,
|
||||
ffi: Permissions::new_unary(Some(&[PathBuf::from("/foo")]), None, false)
|
||||
.unwrap(),
|
||||
net: Permissions::new_unary(Some(&sarr!["127.0.0.1:8000"]), None, false)
|
||||
.unwrap(),
|
||||
env: Permissions::new_unary(Some(&sarr!["HOME"]), None, false).unwrap(),
|
||||
sys: Permissions::new_unary(Some(&sarr!["hostname"]), None, false)
|
||||
.unwrap(),
|
||||
run: Permissions::new_unary(
|
||||
Some(&["deno".to_string().into()]),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
net: Permissions::new_unary(&Some(svec!["127.0.0.1:8000"]), &None, false)
|
||||
.unwrap(),
|
||||
env: Permissions::new_unary(&Some(svec!["HOME"]), &None, false).unwrap(),
|
||||
sys: Permissions::new_unary(&Some(svec!["hostname"]), &None, false)
|
||||
.unwrap(),
|
||||
run: Permissions::new_unary(&Some(svec!["deno"]), &None, false).unwrap(),
|
||||
all: Permissions::new_all(false),
|
||||
};
|
||||
let perms3 = Permissions {
|
||||
read: Permissions::new_unary(
|
||||
&None,
|
||||
&Some(vec![PathBuf::from("/foo")]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
read: Permissions::new_unary(None, Some(&[PathBuf::from("/foo")]), false)
|
||||
.unwrap(),
|
||||
write: Permissions::new_unary(
|
||||
&None,
|
||||
&Some(vec![PathBuf::from("/foo")]),
|
||||
None,
|
||||
Some(&[PathBuf::from("/foo")]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
ffi: Permissions::new_unary(
|
||||
&None,
|
||||
&Some(vec![PathBuf::from("/foo")]),
|
||||
ffi: Permissions::new_unary(None, Some(&[PathBuf::from("/foo")]), false)
|
||||
.unwrap(),
|
||||
net: Permissions::new_unary(None, Some(&sarr!["127.0.0.1:8000"]), false)
|
||||
.unwrap(),
|
||||
env: Permissions::new_unary(None, Some(&sarr!["HOME"]), false).unwrap(),
|
||||
sys: Permissions::new_unary(None, Some(&sarr!["hostname"]), false)
|
||||
.unwrap(),
|
||||
run: Permissions::new_unary(
|
||||
None,
|
||||
Some(&["deno".to_string().into()]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
net: Permissions::new_unary(&None, &Some(svec!["127.0.0.1:8000"]), false)
|
||||
.unwrap(),
|
||||
env: Permissions::new_unary(&None, &Some(svec!["HOME"]), false).unwrap(),
|
||||
sys: Permissions::new_unary(&None, &Some(svec!["hostname"]), false)
|
||||
.unwrap(),
|
||||
run: Permissions::new_unary(&None, &Some(svec!["deno"]), false).unwrap(),
|
||||
all: Permissions::new_all(false),
|
||||
};
|
||||
let perms4 = Permissions {
|
||||
read: Permissions::new_unary(
|
||||
&Some(vec![]),
|
||||
&Some(vec![PathBuf::from("/foo")]),
|
||||
Some(&[]),
|
||||
Some(&[PathBuf::from("/foo")]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
write: Permissions::new_unary(
|
||||
&Some(vec![]),
|
||||
&Some(vec![PathBuf::from("/foo")]),
|
||||
Some(&[]),
|
||||
Some(&[PathBuf::from("/foo")]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
ffi: Permissions::new_unary(
|
||||
&Some(vec![]),
|
||||
&Some(vec![PathBuf::from("/foo")]),
|
||||
Some(&[]),
|
||||
Some(&[PathBuf::from("/foo")]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
net: Permissions::new_unary(
|
||||
&Some(vec![]),
|
||||
&Some(svec!["127.0.0.1:8000"]),
|
||||
Some(&[]),
|
||||
Some(&sarr!["127.0.0.1:8000"]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
env: Permissions::new_unary(&Some(vec![]), &Some(svec!["HOME"]), false)
|
||||
env: Permissions::new_unary(Some(&[]), Some(&sarr!["HOME"]), false)
|
||||
.unwrap(),
|
||||
sys: Permissions::new_unary(
|
||||
&Some(vec![]),
|
||||
&Some(svec!["hostname"]),
|
||||
sys: Permissions::new_unary(Some(&[]), Some(&sarr!["hostname"]), false)
|
||||
.unwrap(),
|
||||
run: Permissions::new_unary(
|
||||
Some(&[]),
|
||||
Some(&["deno".to_string().into()]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
run: Permissions::new_unary(&Some(vec![]), &Some(svec!["deno"]), false)
|
||||
.unwrap(),
|
||||
all: Permissions::new_all(false),
|
||||
};
|
||||
#[rustfmt::skip]
|
||||
|
@ -2894,33 +2916,38 @@ mod tests {
|
|||
set_prompter(Box::new(TestPrompter));
|
||||
let mut perms = Permissions {
|
||||
read: Permissions::new_unary(
|
||||
&Some(vec![PathBuf::from("/foo"), PathBuf::from("/foo/baz")]),
|
||||
&None,
|
||||
Some(&[PathBuf::from("/foo"), PathBuf::from("/foo/baz")]),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
write: Permissions::new_unary(
|
||||
&Some(vec![PathBuf::from("/foo"), PathBuf::from("/foo/baz")]),
|
||||
&None,
|
||||
Some(&[PathBuf::from("/foo"), PathBuf::from("/foo/baz")]),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
ffi: Permissions::new_unary(
|
||||
&Some(vec![PathBuf::from("/foo"), PathBuf::from("/foo/baz")]),
|
||||
&None,
|
||||
Some(&[PathBuf::from("/foo"), PathBuf::from("/foo/baz")]),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
net: Permissions::new_unary(
|
||||
&Some(svec!["127.0.0.1", "127.0.0.1:8000"]),
|
||||
&None,
|
||||
Some(&sarr!["127.0.0.1", "127.0.0.1:8000"]),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
env: Permissions::new_unary(&Some(svec!["HOME"]), &None, false).unwrap(),
|
||||
sys: Permissions::new_unary(&Some(svec!["hostname"]), &None, false)
|
||||
env: Permissions::new_unary(Some(&sarr!["HOME"]), None, false).unwrap(),
|
||||
sys: Permissions::new_unary(Some(&sarr!["hostname"]), None, false)
|
||||
.unwrap(),
|
||||
run: Permissions::new_unary(&Some(svec!["deno"]), &None, false).unwrap(),
|
||||
run: Permissions::new_unary(
|
||||
Some(&["deno".to_string().into()]),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
all: Permissions::new_all(false),
|
||||
};
|
||||
#[rustfmt::skip]
|
||||
|
@ -3006,11 +3033,13 @@ mod tests {
|
|||
.check(&NetDescriptor("deno.land".parse().unwrap(), None), None)
|
||||
.is_err());
|
||||
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
let cwd = std::env::current_dir().unwrap();
|
||||
prompt_value.set(true);
|
||||
assert!(perms.run.check("cat", None).is_ok());
|
||||
assert!(perms.run.check(&cwd.join("cat"), None).is_ok());
|
||||
prompt_value.set(false);
|
||||
assert!(perms.run.check("cat", None).is_ok());
|
||||
assert!(perms.run.check("ls", None).is_err());
|
||||
assert!(perms.run.check(&cwd.join("cat"), None).is_ok());
|
||||
assert!(perms.run.check(&cwd.join("ls"), None).is_err());
|
||||
|
||||
prompt_value.set(true);
|
||||
assert!(perms.env.check("HOME", None).is_ok());
|
||||
|
@ -3102,12 +3131,14 @@ mod tests {
|
|||
.is_ok());
|
||||
|
||||
prompt_value.set(false);
|
||||
assert!(perms.run.check("cat", None).is_err());
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
let cwd = std::env::current_dir().unwrap();
|
||||
assert!(perms.run.check(&cwd.join("cat"), None).is_err());
|
||||
prompt_value.set(true);
|
||||
assert!(perms.run.check("cat", None).is_err());
|
||||
assert!(perms.run.check("ls", None).is_ok());
|
||||
assert!(perms.run.check(&cwd.join("cat"), None).is_err());
|
||||
assert!(perms.run.check(&cwd.join("ls"), None).is_ok());
|
||||
prompt_value.set(false);
|
||||
assert!(perms.run.check("ls", None).is_ok());
|
||||
assert!(perms.run.check(&cwd.join("ls"), None).is_ok());
|
||||
|
||||
prompt_value.set(false);
|
||||
assert!(perms.env.check("HOME", None).is_err());
|
||||
|
@ -3134,7 +3165,7 @@ mod tests {
|
|||
let mut perms = Permissions::allow_all();
|
||||
perms.env = UnaryPermission {
|
||||
granted_global: false,
|
||||
..Permissions::new_unary(&Some(svec!["HOME"]), &None, false).unwrap()
|
||||
..Permissions::new_unary(Some(&sarr!["HOME"]), None, false).unwrap()
|
||||
};
|
||||
|
||||
prompt_value.set(true);
|
||||
|
@ -3150,14 +3181,14 @@ mod tests {
|
|||
fn test_check_partial_denied() {
|
||||
let mut perms = Permissions {
|
||||
read: Permissions::new_unary(
|
||||
&Some(vec![]),
|
||||
&Some(vec![PathBuf::from("/foo/bar")]),
|
||||
Some(&[]),
|
||||
Some(&[PathBuf::from("/foo/bar")]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
write: Permissions::new_unary(
|
||||
&Some(vec![]),
|
||||
&Some(vec![PathBuf::from("/foo/bar")]),
|
||||
Some(&[]),
|
||||
Some(&[PathBuf::from("/foo/bar")]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
|
@ -3175,8 +3206,8 @@ mod tests {
|
|||
fn test_net_fully_qualified_domain_name() {
|
||||
let mut perms = Permissions {
|
||||
net: Permissions::new_unary(
|
||||
&Some(vec!["allowed.domain".to_string(), "1.1.1.1".to_string()]),
|
||||
&Some(vec!["denied.domain".to_string(), "2.2.2.2".to_string()]),
|
||||
Some(&["allowed.domain".to_string(), "1.1.1.1".to_string()]),
|
||||
Some(&["denied.domain".to_string(), "2.2.2.2".to_string()]),
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
|
@ -3341,8 +3372,8 @@ mod tests {
|
|||
fn test_create_child_permissions() {
|
||||
set_prompter(Box::new(TestPrompter));
|
||||
let mut main_perms = Permissions {
|
||||
env: Permissions::new_unary(&Some(vec![]), &None, false).unwrap(),
|
||||
net: Permissions::new_unary(&Some(svec!["foo", "bar"]), &None, false)
|
||||
env: Permissions::new_unary(Some(&[]), None, false).unwrap(),
|
||||
net: Permissions::new_unary(Some(&sarr!["foo", "bar"]), None, false)
|
||||
.unwrap(),
|
||||
..Permissions::none_without_prompt()
|
||||
};
|
||||
|
@ -3358,8 +3389,8 @@ mod tests {
|
|||
)
|
||||
.unwrap(),
|
||||
Permissions {
|
||||
env: Permissions::new_unary(&Some(vec![]), &None, false).unwrap(),
|
||||
net: Permissions::new_unary(&Some(svec!["foo"]), &None, false).unwrap(),
|
||||
env: Permissions::new_unary(Some(&[]), None, false).unwrap(),
|
||||
net: Permissions::new_unary(Some(&sarr!["foo"]), None, false).unwrap(),
|
||||
..Permissions::none_without_prompt()
|
||||
}
|
||||
);
|
||||
|
@ -3445,20 +3476,20 @@ mod tests {
|
|||
set_prompter(Box::new(TestPrompter));
|
||||
|
||||
assert!(Permissions::new_unary::<ReadDescriptor>(
|
||||
&Some(vec![Default::default()]),
|
||||
&None,
|
||||
Some(&[Default::default()]),
|
||||
None,
|
||||
false
|
||||
)
|
||||
.is_err());
|
||||
assert!(Permissions::new_unary::<EnvDescriptor>(
|
||||
&Some(vec![Default::default()]),
|
||||
&None,
|
||||
Some(&[Default::default()]),
|
||||
None,
|
||||
false
|
||||
)
|
||||
.is_err());
|
||||
assert!(Permissions::new_unary::<NetDescriptor>(
|
||||
&Some(vec![Default::default()]),
|
||||
&None,
|
||||
Some(&[Default::default()]),
|
||||
None,
|
||||
false
|
||||
)
|
||||
.is_err());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue