diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2022-12-07 20:21:18 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-07 20:21:18 +0100 |
commit | 1a472ad06bdc55b1fa0c0f26ca2d24d709f2e0c3 (patch) | |
tree | 7b1c8b615f36916744723e8d60162801eb6127a7 | |
parent | 192f07bb7e2076808cae1eeb6c701cdd3d8d42cd (diff) |
feat(repl): run "deno repl" with no permissions (#16795)
This commit changes "deno repl" command to run with no permissions by
default and accept "--allow-*" flags.
This change is dictated by the fact that currently there is no way to
run REPL with limited permissions. Technically it's a breaking
change in the CLI command, but there's agreement in the team
that it has merit and it's a good solution.
Running just "deno" command still starts the REPL with full permissions
allowed, but now a banner is printed to inform users about that:
-rw-r--r-- | cli/args/flags.rs | 76 | ||||
-rw-r--r-- | cli/main.rs | 8 | ||||
-rw-r--r-- | cli/tests/inspector_tests.rs | 1 | ||||
-rw-r--r-- | cli/tests/repl_tests.rs | 10 | ||||
-rw-r--r-- | cli/tools/repl/mod.rs | 16 |
5 files changed, 48 insertions, 63 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 4296fbc77..7a4416cf5 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -163,6 +163,7 @@ pub struct LintFlags { pub struct ReplFlags { pub eval_files: Option<Vec<String>>, pub eval: Option<String>, + pub is_default_command: bool, } #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] @@ -245,6 +246,7 @@ impl Default for DenoSubcommand { DenoSubcommand::Repl(ReplFlags { eval_files: None, eval: None, + is_default_command: true, }) } } @@ -624,6 +626,7 @@ pub fn flags_from_vec(args: Vec<String>) -> clap::Result<Flags> { ReplFlags { eval_files: None, eval: None, + is_default_command: true, }, ), } @@ -632,15 +635,18 @@ pub fn flags_from_vec(args: Vec<String>) -> clap::Result<Flags> { } fn handle_repl_flags(flags: &mut Flags, repl_flags: ReplFlags) { + // If user runs just `deno` binary we enter REPL and allow all permissions. + if repl_flags.is_default_command { + flags.allow_net = Some(vec![]); + flags.allow_env = Some(vec![]); + flags.allow_run = Some(vec![]); + flags.allow_read = Some(vec![]); + flags.allow_sys = Some(vec![]); + flags.allow_write = Some(vec![]); + flags.allow_ffi = Some(vec![]); + flags.allow_hrtime = true; + } flags.subcommand = DenoSubcommand::Repl(repl_flags); - flags.allow_net = Some(vec![]); - flags.allow_env = Some(vec![]); - flags.allow_run = Some(vec![]); - flags.allow_read = Some(vec![]); - flags.allow_sys = Some(vec![]); - flags.allow_write = Some(vec![]); - flags.allow_ffi = Some(vec![]); - flags.allow_hrtime = true; } fn clap_root(version: &str) -> Command { @@ -1464,7 +1470,7 @@ Ignore linting a file by adding an ignore comment at the top of the file: } fn repl_subcommand<'a>() -> Command<'a> { - runtime_args(Command::new("repl"), false, true) + runtime_args(Command::new("repl"), true, true) .about("Read Eval Print Loop") .arg( Arg::new("eval-file") @@ -1483,7 +1489,6 @@ fn repl_subcommand<'a>() -> Command<'a> { .takes_value(true) .value_name("code"), ) - .arg(unsafely_ignore_certificate_errors_arg()) } fn run_subcommand<'a>() -> Command<'a> { @@ -2654,7 +2659,7 @@ fn lint_parse(flags: &mut Flags, matches: &clap::ArgMatches) { } fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - runtime_args_parse(flags, matches, false, true); + runtime_args_parse(flags, matches, true, true); unsafely_ignore_certificate_errors_parse(flags, matches); let eval_files: Option<Vec<String>> = matches @@ -2666,6 +2671,7 @@ fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) { ReplFlags { eval_files, eval: matches.value_of("eval").map(ToOwned::to_owned), + is_default_command: false, }, ); } @@ -4276,7 +4282,8 @@ mod tests { Flags { subcommand: DenoSubcommand::Repl(ReplFlags { eval_files: None, - eval: None + eval: None, + is_default_command: true, }), allow_net: Some(vec![]), unsafely_ignore_certificate_errors: None, @@ -4295,13 +4302,14 @@ mod tests { #[test] fn repl_with_flags() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "repl", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--unsafely-ignore-certificate-errors"]); + let r = flags_from_vec(svec!["deno", "repl", "-A", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--unsafely-ignore-certificate-errors"]); assert_eq!( r.unwrap(), Flags { subcommand: DenoSubcommand::Repl(ReplFlags { eval_files: None, - eval: None + eval: None, + is_default_command: false, }), import_map_path: Some("import_map.json".to_string()), no_remote: true, @@ -4316,6 +4324,7 @@ mod tests { v8_flags: svec!["--help", "--random-seed=1"], seed: Some(1), inspect: Some("127.0.0.1:9229".parse().unwrap()), + allow_all: true, allow_net: Some(vec![]), allow_env: Some(vec![]), allow_run: Some(vec![]), @@ -4333,22 +4342,16 @@ mod tests { #[test] fn repl_with_eval_flag() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "repl", "--eval", "console.log('hello');"]); + let r = flags_from_vec(svec!["deno", "repl", "--allow-write", "--eval", "console.log('hello');"]); assert_eq!( r.unwrap(), Flags { subcommand: DenoSubcommand::Repl(ReplFlags { eval_files: None, eval: Some("console.log('hello');".to_string()), + is_default_command: false, }), - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, type_check_mode: TypeCheckMode::None, ..Flags::default() } @@ -4369,15 +4372,8 @@ mod tests { "https://examples.deno.land/hello-world.ts".to_string() ]), eval: None, + is_default_command: false, }), - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, type_check_mode: TypeCheckMode::None, ..Flags::default() } @@ -5172,16 +5168,9 @@ mod tests { subcommand: DenoSubcommand::Repl(ReplFlags { eval_files: None, eval: Some("console.log('hello');".to_string()), + is_default_command: false, }), unsafely_ignore_certificate_errors: Some(vec![]), - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, type_check_mode: TypeCheckMode::None, ..Flags::default() } @@ -5246,7 +5235,8 @@ mod tests { Flags { subcommand: DenoSubcommand::Repl(ReplFlags { eval_files: None, - eval: None + eval: None, + is_default_command: false, }), unsafely_ignore_certificate_errors: Some(svec![ "deno.land", @@ -5256,14 +5246,6 @@ mod tests { "[::1]", "1.2.3.4" ]), - allow_net: Some(vec![]), - allow_env: Some(vec![]), - allow_run: Some(vec![]), - allow_read: Some(vec![]), - allow_sys: Some(vec![]), - allow_write: Some(vec![]), - allow_ffi: Some(vec![]), - allow_hrtime: true, type_check_mode: TypeCheckMode::None, ..Flags::default() } diff --git a/cli/main.rs b/cli/main.rs index 445649e5f..98700c2b7 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -585,13 +585,7 @@ async fn repl_command( ) .await?; worker.setup_repl().await?; - tools::repl::run( - &ps, - worker.into_main_worker(), - repl_flags.eval_files, - repl_flags.eval, - ) - .await + tools::repl::run(&ps, worker.into_main_worker(), repl_flags).await } async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> { diff --git a/cli/tests/inspector_tests.rs b/cli/tests/inspector_tests.rs index 8e5a8d1f6..0cf8cc3bb 100644 --- a/cli/tests/inspector_tests.rs +++ b/cli/tests/inspector_tests.rs @@ -557,6 +557,7 @@ mod inspector { async fn inspector_runtime_evaluate_does_not_crash() { let child = util::deno_cmd() .arg("repl") + .arg("--allow-read") .arg(inspect_flag_with_unique_port("--inspect")) .stdin(std::process::Stdio::piped()) .stdout(std::process::Stdio::piped()) diff --git a/cli/tests/repl_tests.rs b/cli/tests/repl_tests.rs index 136148d9f..4524b4097 100644 --- a/cli/tests/repl_tests.rs +++ b/cli/tests/repl_tests.rs @@ -460,9 +460,9 @@ mod repl { #[test] fn import() { - let (out, _) = util::run_and_collect_output( + let (out, _) = util::run_and_collect_output_with_args( true, - "repl", + vec![], Some(vec!["import('./subdir/auto_print_hello.ts')"]), Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), false, @@ -472,9 +472,9 @@ mod repl { #[test] fn import_declarations() { - let (out, _) = util::run_and_collect_output( + let (out, _) = util::run_and_collect_output_with_args( true, - "repl", + vec!["repl", "--allow-read"], Some(vec!["import './subdir/auto_print_hello.ts';"]), Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), false, @@ -796,7 +796,7 @@ mod repl { fn eval_file_flag_multiple_files() { let (out, err) = util::run_and_collect_output_with_args( true, - vec!["repl", "--eval-file=http://127.0.0.1:4545/repl/import_type.ts,./tsc/d.ts,http://127.0.0.1:4545/type_definitions/foo.js"], + vec!["repl", "--allow-read", "--eval-file=http://127.0.0.1:4545/repl/import_type.ts,./tsc/d.ts,http://127.0.0.1:4545/type_definitions/foo.js"], Some(vec!["b.method1=v4", "b.method1()+foo.toUpperCase()"]), None, true, diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index afbd39eff..502105139 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -1,5 +1,7 @@ // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. +use crate::args::ReplFlags; +use crate::colors; use crate::proc_state::ProcState; use deno_core::error::AnyError; use deno_runtime::permissions::Permissions; @@ -77,8 +79,7 @@ async fn read_eval_file( pub async fn run( ps: &ProcState, worker: MainWorker, - maybe_eval_files: Option<Vec<String>>, - maybe_eval: Option<String>, + repl_flags: ReplFlags, ) -> Result<i32, AnyError> { let mut repl_session = ReplSession::initialize(worker).await?; let mut rustyline_channel = rustyline_channel(); @@ -92,7 +93,7 @@ pub async fn run( let history_file_path = ps.dir.repl_history_file_path(); let editor = ReplEditor::new(helper, history_file_path)?; - if let Some(eval_files) = maybe_eval_files { + if let Some(eval_files) = repl_flags.eval_files { for eval_file in eval_files { match read_eval_file(ps, &eval_file).await { Ok(eval_source) => { @@ -114,7 +115,7 @@ pub async fn run( } } - if let Some(eval) = maybe_eval { + if let Some(eval) = repl_flags.eval { let output = repl_session.evaluate_line_and_get_output(&eval).await?; // only output errors if let EvaluationOutput::Error(error_text) = output { @@ -127,6 +128,13 @@ pub async fn run( if !ps.options.is_quiet() { println!("Deno {}", crate::version::deno()); println!("exit using ctrl+d, ctrl+c, or close()"); + if repl_flags.is_default_command { + println!( + "{}", + colors::yellow("REPL is running with all permissions allowed.") + ); + println!("To specify permissions, run `deno repl` with allow flags.") + } } loop { |