summaryrefslogtreecommitdiff
path: root/cli/args/mod.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2024-09-26 02:50:54 +0100
committerGitHub <noreply@github.com>2024-09-26 01:50:54 +0000
commit5504acea6751480f1425c88353ad5d36257bdce7 (patch)
treefa02e6c546eae469aac894bfc71600ab4eccad28 /cli/args/mod.rs
parent05415bb9de475aa8646985a545f30fe93136207e (diff)
feat: add `--allow-import` flag (#25469)
This replaces `--allow-net` for import permissions and makes the security sandbox stricter by also checking permissions for statically analyzable imports. By default, this has a value of `--allow-import=deno.land:443,jsr.io:443,esm.sh:443,raw.githubusercontent.com:443,gist.githubusercontent.com:443`, but that can be overridden by providing a different set of hosts. Additionally, when no value is provided, import permissions are inferred from the CLI arguments so the following works because `fresh.deno.dev:443` will be added to the list of allowed imports: ```ts deno run -A -r https://fresh.deno.dev ``` --------- Co-authored-by: David Sherret <dsherret@gmail.com>
Diffstat (limited to 'cli/args/mod.rs')
-rw-r--r--cli/args/mod.rs102
1 files changed, 67 insertions, 35 deletions
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index 1c92777ae..80b9afb24 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -769,6 +769,7 @@ pub struct CliOptions {
// application need not concern itself with, so keep these private
flags: Arc<Flags>,
initial_cwd: PathBuf,
+ main_module_cell: std::sync::OnceLock<Result<ModuleSpecifier, AnyError>>,
maybe_node_modules_folder: Option<PathBuf>,
npmrc: Arc<ResolvedNpmRc>,
maybe_lockfile: Option<Arc<CliLockfile>>,
@@ -825,6 +826,7 @@ impl CliOptions {
npmrc,
maybe_node_modules_folder,
overrides: Default::default(),
+ main_module_cell: std::sync::OnceLock::new(),
start_dir,
deno_dir_provider,
})
@@ -1105,40 +1107,43 @@ impl CliOptions {
self.flags.env_file.as_ref()
}
- pub fn resolve_main_module(&self) -> Result<ModuleSpecifier, AnyError> {
- let main_module = match &self.flags.subcommand {
- DenoSubcommand::Compile(compile_flags) => {
- resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())?
- }
- DenoSubcommand::Eval(_) => {
- resolve_url_or_path("./$deno$eval.ts", self.initial_cwd())?
- }
- DenoSubcommand::Repl(_) => {
- resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())?
- }
- DenoSubcommand::Run(run_flags) => {
- if run_flags.is_stdin() {
- std::env::current_dir()
- .context("Unable to get CWD")
- .and_then(|cwd| {
- resolve_url_or_path("./$deno$stdin.ts", &cwd)
- .map_err(AnyError::from)
- })?
- } else if NpmPackageReqReference::from_str(&run_flags.script).is_ok() {
- ModuleSpecifier::parse(&run_flags.script)?
- } else {
- resolve_url_or_path(&run_flags.script, self.initial_cwd())?
- }
- }
- DenoSubcommand::Serve(run_flags) => {
- resolve_url_or_path(&run_flags.script, self.initial_cwd())?
- }
- _ => {
- bail!("No main module.")
- }
- };
+ pub fn resolve_main_module(&self) -> Result<&ModuleSpecifier, AnyError> {
+ self
+ .main_module_cell
+ .get_or_init(|| {
+ let main_module = match &self.flags.subcommand {
+ DenoSubcommand::Compile(compile_flags) => {
+ resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())?
+ }
+ DenoSubcommand::Eval(_) => {
+ resolve_url_or_path("./$deno$eval.ts", self.initial_cwd())?
+ }
+ DenoSubcommand::Repl(_) => {
+ resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())?
+ }
+ DenoSubcommand::Run(run_flags) => {
+ if run_flags.is_stdin() {
+ resolve_url_or_path("./$deno$stdin.ts", self.initial_cwd())?
+ } else if NpmPackageReqReference::from_str(&run_flags.script)
+ .is_ok()
+ {
+ ModuleSpecifier::parse(&run_flags.script)?
+ } else {
+ resolve_url_or_path(&run_flags.script, self.initial_cwd())?
+ }
+ }
+ DenoSubcommand::Serve(run_flags) => {
+ resolve_url_or_path(&run_flags.script, self.initial_cwd())?
+ }
+ _ => {
+ bail!("No main module.")
+ }
+ };
- Ok(main_module)
+ Ok(main_module)
+ })
+ .as_ref()
+ .map_err(|err| deno_core::anyhow::anyhow!("{}", err))
}
pub fn resolve_file_header_overrides(
@@ -1159,7 +1164,7 @@ impl CliOptions {
(maybe_main_specifier, maybe_content_type)
{
HashMap::from([(
- main_specifier,
+ main_specifier.clone(),
HashMap::from([("content-type".to_string(), content_type.to_string())]),
)])
} else {
@@ -1480,7 +1485,34 @@ impl CliOptions {
}
pub fn permissions_options(&self) -> PermissionsOptions {
- self.flags.permissions.to_options()
+ fn files_to_urls(files: &[String]) -> Vec<Cow<'_, Url>> {
+ files
+ .iter()
+ .filter_map(|f| Url::parse(f).ok().map(Cow::Owned))
+ .collect()
+ }
+
+ // get a list of urls to imply for --allow-import
+ let cli_arg_urls = self
+ .resolve_main_module()
+ .ok()
+ .map(|url| vec![Cow::Borrowed(url)])
+ .or_else(|| match &self.flags.subcommand {
+ DenoSubcommand::Cache(cache_flags) => {
+ Some(files_to_urls(&cache_flags.files))
+ }
+ DenoSubcommand::Check(check_flags) => {
+ Some(files_to_urls(&check_flags.files))
+ }
+ DenoSubcommand::Install(InstallFlags {
+ kind: InstallKind::Global(flags),
+ }) => Url::parse(&flags.module_url)
+ .ok()
+ .map(|url| vec![Cow::Owned(url)]),
+ _ => None,
+ })
+ .unwrap_or_default();
+ self.flags.permissions.to_options(&cli_arg_urls)
}
pub fn reload_flag(&self) -> bool {