1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 21:50:00 -05:00

fix(cli): restore permission check on workers (#8123)

Fixes #8120
This commit is contained in:
Kitson Kelly 2020-10-27 06:56:00 +11:00 committed by GitHub
parent acc201625f
commit b03f4a4a1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 110 additions and 9 deletions

View file

@ -7,6 +7,7 @@ use deno_core::error::custom_error;
use deno_core::error::uri_error;
use deno_core::error::AnyError;
use deno_core::url;
use deno_core::ModuleSpecifier;
use serde::Deserialize;
use std::collections::HashSet;
use std::env::current_dir;
@ -548,6 +549,21 @@ impl Permissions {
.check(&format!("network access to \"{}\"", url), "--allow-net")
}
/// A helper function that determines if the module specifier is a local or
/// remote, and performs a read or net check for the specifier.
pub fn check_specifier(
&self,
specifier: &ModuleSpecifier,
) -> Result<(), AnyError> {
let url = specifier.as_url();
if url.scheme() == "file" {
let path = url.to_file_path().unwrap();
self.check_read(&path)
} else {
self.check_net_url(url)
}
}
pub fn check_env(&self) -> Result<(), AnyError> {
self
.env
@ -830,6 +846,57 @@ mod tests {
}
}
#[test]
fn check_specifiers() {
let read_allowlist = if cfg!(target_os = "windows") {
vec![PathBuf::from("C:\\a")]
} else {
vec![PathBuf::from("/a")]
};
let perms = Permissions::from_flags(&Flags {
read_allowlist,
net_allowlist: svec!["localhost"],
..Default::default()
});
let mut fixtures = vec![
(
ModuleSpecifier::resolve_url_or_path("http://localhost:4545/mod.ts")
.unwrap(),
true,
),
(
ModuleSpecifier::resolve_url_or_path("http://deno.land/x/mod.ts")
.unwrap(),
false,
),
];
if cfg!(target_os = "windows") {
fixtures.push((
ModuleSpecifier::resolve_url_or_path("file:///C:/a/mod.ts").unwrap(),
true,
));
fixtures.push((
ModuleSpecifier::resolve_url_or_path("file:///C:/b/mod.ts").unwrap(),
false,
));
} else {
fixtures.push((
ModuleSpecifier::resolve_url_or_path("file:///a/mod.ts").unwrap(),
true,
));
fixtures.push((
ModuleSpecifier::resolve_url_or_path("file:///b/mod.ts").unwrap(),
false,
));
}
for (specifier, expected) in fixtures {
assert_eq!(perms.check_specifier(&specifier).is_ok(), expected);
}
}
#[test]
fn test_deserialize_perms() {
let json_perms = r#"

View file

@ -121,13 +121,19 @@ impl ProgramState {
self: &Arc<Self>,
specifier: ModuleSpecifier,
target_lib: TargetLib,
dynamic_permissions: Permissions,
runtime_permissions: Permissions,
is_dynamic: bool,
maybe_import_map: Option<ImportMap>,
) -> Result<(), AnyError> {
let specifier = specifier.clone();
// Workers are subject to the current runtime permissions. We do the
// permission check here early to avoid "wasting" time building a module
// graph for a module that cannot be loaded.
if target_lib == TargetLib::Worker {
runtime_permissions.check_specifier(&specifier)?;
}
let handler =
Rc::new(RefCell::new(FetchHandler::new(self, dynamic_permissions)?));
Rc::new(RefCell::new(FetchHandler::new(self, runtime_permissions)?));
let mut builder =
GraphBuilder2::new(handler, maybe_import_map, self.lockfile.clone());
builder.add(&specifier, is_dynamic).await?;

View file

@ -215,8 +215,9 @@ impl CompiledFileMetadata {
pub struct FetchHandler {
/// An instance of disk where generated (emitted) files are stored.
disk_cache: DiskCache,
/// A set of permissions to apply to dynamic imports.
dynamic_permissions: Permissions,
/// The set of current runtime permissions which need to be applied to
/// dynamic imports.
runtime_permissions: Permissions,
/// A clone of the `program_state` file fetcher.
file_fetcher: SourceFileFetcher,
}
@ -224,7 +225,7 @@ pub struct FetchHandler {
impl FetchHandler {
pub fn new(
program_state: &Arc<ProgramState>,
dynamic_permissions: Permissions,
runtime_permissions: Permissions,
) -> Result<Self, AnyError> {
let custom_root = env::var("DENO_DIR").map(String::into).ok();
let deno_dir = DenoDir::new(custom_root)?;
@ -233,7 +234,7 @@ impl FetchHandler {
Ok(FetchHandler {
disk_cache,
dynamic_permissions,
runtime_permissions,
file_fetcher,
})
}
@ -250,7 +251,7 @@ impl SpecifierHandler for FetchHandler {
// permissions need to be applied. Other static imports have all
// permissions.
let permissions = if is_dynamic {
self.dynamic_permissions.clone()
self.runtime_permissions.clone()
} else {
Permissions::allow_all()
};
@ -445,7 +446,7 @@ pub mod tests {
let fetch_handler = FetchHandler {
disk_cache,
dynamic_permissions: Permissions::default(),
runtime_permissions: Permissions::default(),
file_fetcher,
};

View file

@ -0,0 +1,4 @@
new Worker(
new URL("./subdeb/worker_types.ts", import.meta.url).toString(),
{ type: "module" },
);

View file

@ -0,0 +1,3 @@
[WILDCARD]
error: Uncaught (in worker "") read access to "[WILDCARD]worker_types.ts", run again with the --allow-read flag
[WILDCARD]

View file

@ -0,0 +1,4 @@
new Worker(
"http://localhost:4545/cli/tests/subdir/worker_types.ts",
{ type: "module" },
);

View file

@ -0,0 +1,3 @@
[WILDCARD]
error: Uncaught (in worker "") network access to "http://localhost:4545/cli/tests/subdir/worker_types.ts", run again with the --allow-net flag
[WILDCARD]

View file

@ -2467,6 +2467,19 @@ itest!(error_local_static_import_from_remote_js {
output: "error_local_static_import_from_remote.js.out",
});
itest!(error_worker_permissions_local {
args: "run --reload error_worker_permissions_local.ts",
output: "error_worker_permissions_local.ts.out",
exit_code: 1,
});
itest!(error_worker_permissions_remote {
args: "run --reload error_worker_permissions_remote.ts",
http_server: true,
output: "error_worker_permissions_remote.ts.out",
exit_code: 1,
});
itest!(exit_error42 {
exit_code: 42,
args: "run --quiet --reload exit_error42.ts",

View file

@ -135,7 +135,7 @@ lazy_static! {
Regex::new(r#"(?i)\slib\s*=\s*["']([^"']*)["']"#).unwrap();
}
#[derive(Clone)]
#[derive(Clone, Eq, PartialEq)]
pub enum TargetLib {
Main,
Worker,