mirror of
https://github.com/denoland/deno.git
synced 2024-10-29 08:58:01 -04:00
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:
This commit is contained in:
parent
192f07bb7e
commit
1a472ad06b
5 changed files with 48 additions and 63 deletions
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue