From 353a4a1af3165b2c59319865350d70a99105269c Mon Sep 17 00:00:00 2001 From: TheAifam5 Date: Mon, 9 Aug 2021 16:53:21 +0200 Subject: feat: Add --unsafely-treat-insecure-origin-as-secure flag to disable SSL verification (#11324) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds "--unsafely-treat-insecure-origin-as-secure" flag that allows to disable SSL verification for all domains, or specific domains if they were passed as an argument to the flag. Co-authored-by: Bartek IwaƄczuk --- cli/file_fetcher.rs | 11 ++++ cli/flags.rs | 89 +++++++++++++++++++++++++- cli/http_util.rs | 9 ++- cli/lsp/registries.rs | 2 + cli/main.rs | 8 +++ cli/program_state.rs | 17 +++++ cli/specifier_handler.rs | 1 + cli/standalone.rs | 3 + cli/tests/cafile_ts_fetch_unsafe_ssl.ts.out | 2 + cli/tests/cafile_url_imports_unsafe_ssl.ts.out | 3 + cli/tests/integration/mod.rs | 13 ++++ cli/tools/standalone.rs | 5 ++ 12 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 cli/tests/cafile_ts_fetch_unsafe_ssl.ts.out create mode 100644 cli/tests/cafile_url_imports_unsafe_ssl.ts.out (limited to 'cli') diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index 207f08c64..e61c3beb9 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -223,6 +223,7 @@ impl FileFetcher { allow_remote: bool, root_cert_store: Option, blob_store: BlobStore, + unsafely_treat_insecure_origin_as_secure: Option>, ) -> Result { Ok(Self { auth_tokens: AuthTokens::new(env::var(DENO_AUTH_TOKENS).ok()), @@ -235,6 +236,7 @@ impl FileFetcher { root_cert_store, None, None, + unsafely_treat_insecure_origin_as_secure, )?, blob_store, }) @@ -618,6 +620,7 @@ mod tests { true, None, blob_store.clone(), + None, ) .expect("setup failed"); (file_fetcher, temp_dir, blob_store) @@ -1063,6 +1066,7 @@ mod tests { true, None, BlobStore::default(), + None, ) .expect("setup failed"); let result = file_fetcher @@ -1090,6 +1094,7 @@ mod tests { true, None, BlobStore::default(), + None, ) .expect("could not create file fetcher"); let specifier = @@ -1118,6 +1123,7 @@ mod tests { true, None, BlobStore::default(), + None, ) .expect("could not create file fetcher"); let result = file_fetcher_02 @@ -1279,6 +1285,7 @@ mod tests { true, None, BlobStore::default(), + None, ) .expect("could not create file fetcher"); let specifier = @@ -1310,6 +1317,7 @@ mod tests { true, None, BlobStore::default(), + None, ) .expect("could not create file fetcher"); let result = file_fetcher_02 @@ -1420,6 +1428,7 @@ mod tests { false, None, BlobStore::default(), + None, ) .expect("could not create file fetcher"); let specifier = @@ -1447,6 +1456,7 @@ mod tests { true, None, BlobStore::default(), + None, ) .expect("could not create file fetcher"); let file_fetcher_02 = FileFetcher::new( @@ -1455,6 +1465,7 @@ mod tests { true, None, BlobStore::default(), + None, ) .expect("could not create file fetcher"); let specifier = diff --git a/cli/flags.rs b/cli/flags.rs index 1c7eaf9a0..36b326c0b 100644 --- a/cli/flags.rs +++ b/cli/flags.rs @@ -164,6 +164,7 @@ pub struct Flags { pub repl: bool, pub seed: Option, pub unstable: bool, + pub unsafely_treat_insecure_origin_as_secure: Option>, pub v8_flags: Vec, pub version: bool, pub watch: bool, @@ -216,6 +217,20 @@ impl Flags { _ => {} } + match &self.unsafely_treat_insecure_origin_as_secure { + Some(ic_allowlist) if ic_allowlist.is_empty() => { + args.push("--unsafely-treat-insecure-origin-as-secure".to_string()); + } + Some(ic_allowlist) => { + let s = format!( + "--unsafely-treat-insecure-origin-as-secure={}", + ic_allowlist.join(",") + ); + args.push(s); + } + _ => {} + } + match &self.allow_env { Some(env_allowlist) if env_allowlist.is_empty() => { args.push("--allow-env".to_string()); @@ -1221,6 +1236,16 @@ fn permission_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { .help("Allow network access") .validator(crate::flags_allow_net::validator), ) + .arg( + Arg::with_name("unsafely-treat-insecure-origin-as-secure") + .long("unsafely-treat-insecure-origin-as-secure") + .min_values(0) + .takes_value(true) + .use_delimiter(true) + .require_equals(true) + .help("DANGER: Disables verification of SSL certificates") + .validator(crate::flags_allow_net::validator), + ) .arg( Arg::with_name("allow-env") .long("allow-env") @@ -1879,7 +1904,15 @@ fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { crate::flags_allow_net::parse(net_wl.map(ToString::to_string).collect()) .unwrap(); flags.allow_net = Some(net_allowlist); - debug!("net allowlist: {:#?}", &flags.allow_net); + } + + if let Some(ic_wl) = + matches.values_of("unsafely-treat-insecure-origin-as-secure") + { + let ic_allowlist: Vec = + crate::flags_allow_net::parse(ic_wl.map(ToString::to_string).collect()) + .unwrap(); + flags.unsafely_treat_insecure_origin_as_secure = Some(ic_allowlist); } if let Some(env_wl) = matches.values_of("allow-env") { @@ -2723,6 +2756,7 @@ mod tests { repl: true, subcommand: DenoSubcommand::Repl { eval: None }, allow_net: Some(vec![]), + unsafely_treat_insecure_origin_as_secure: None, allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), @@ -3198,7 +3232,7 @@ mod tests { #[test] fn install_with_flags() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "install", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--name", "file_server", "--root", "/foo", "--force", "https://deno.land/std/http/file_server.ts", "foo", "bar"]); + let r = flags_from_vec(svec!["deno", "install", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-treat-insecure-origin-as-secure", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--name", "file_server", "--root", "/foo", "--force", "https://deno.land/std/http/file_server.ts", "foo", "bar"]); assert_eq!( r.unwrap(), Flags { @@ -3222,6 +3256,7 @@ mod tests { seed: Some(1), inspect: Some("127.0.0.1:9229".parse().unwrap()), allow_net: Some(vec![]), + unsafely_treat_insecure_origin_as_secure: Some(vec![]), allow_read: Some(vec![]), ..Flags::default() } @@ -3366,6 +3401,53 @@ mod tests { ); } + #[test] + fn unsafely_treat_insecure_origin_as_secure() { + let r = flags_from_vec(svec![ + "deno", + "run", + "--unsafely-treat-insecure-origin-as-secure", + "script.ts" + ]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Run { + script: "script.ts".to_string(), + }, + unsafely_treat_insecure_origin_as_secure: Some(vec![]), + ..Flags::default() + } + ); + } + + #[test] + fn unsafely_treat_insecure_origin_as_secure_with_ipv6_address() { + let r = flags_from_vec(svec![ + "deno", + "run", + "--unsafely-treat-insecure-origin-as-secure=deno.land,localhost,::,127.0.0.1,[::1],1.2.3.4", + "script.ts" + ]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Run { + script: "script.ts".to_string(), + }, + unsafely_treat_insecure_origin_as_secure: Some(svec![ + "deno.land", + "localhost", + "::", + "127.0.0.1", + "[::1]", + "1.2.3.4" + ]), + ..Flags::default() + } + ); + } + #[test] fn no_remote() { let r = flags_from_vec(svec!["deno", "run", "--no-remote", "script.ts"]); @@ -3845,7 +3927,7 @@ mod tests { #[test] fn compile_with_flags() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "compile", "--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", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--output", "colors", "https://deno.land/std/examples/colors.ts", "foo", "bar"]); + let r = flags_from_vec(svec!["deno", "compile", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--unsafely-treat-insecure-origin-as-secure", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--location", "https:foo", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--output", "colors", "https://deno.land/std/examples/colors.ts", "foo", "bar"]); assert_eq!( r.unwrap(), Flags { @@ -3866,6 +3948,7 @@ mod tests { cached_only: true, location: Some(Url::parse("https://foo/").unwrap()), allow_read: Some(vec![]), + unsafely_treat_insecure_origin_as_secure: Some(vec![]), allow_net: Some(vec![]), v8_flags: svec!["--help", "--random-seed=1"], seed: Some(1), diff --git a/cli/http_util.rs b/cli/http_util.rs index 671093923..ac8e1dff6 100644 --- a/cli/http_util.rs +++ b/cli/http_util.rs @@ -145,7 +145,8 @@ mod tests { use std::fs::read; fn create_test_client(ca_data: Option>) -> Client { - create_http_client("test_client".to_string(), None, ca_data, None).unwrap() + create_http_client("test_client".to_string(), None, ca_data, None, None) + .unwrap() } #[tokio::test] @@ -347,6 +348,7 @@ mod tests { .unwrap(), ), None, + None, ) .unwrap(); let result = fetch_once(FetchOnceArgs { @@ -376,6 +378,7 @@ mod tests { None, // This will load mozilla certs by default None, None, + None, ) .unwrap(); @@ -407,6 +410,7 @@ mod tests { Some(RootCertStore::empty()), // no certs loaded at all None, None, + None, ) .unwrap(); @@ -445,6 +449,7 @@ mod tests { .unwrap(), ), None, + None, ) .unwrap(); let result = fetch_once(FetchOnceArgs { @@ -484,6 +489,7 @@ mod tests { .unwrap(), ), None, + None, ) .unwrap(); let result = fetch_once(FetchOnceArgs { @@ -537,6 +543,7 @@ mod tests { .unwrap(), ), None, + None, ) .unwrap(); let result = fetch_once(FetchOnceArgs { diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs index 6a1dc1a4b..1bf140019 100644 --- a/cli/lsp/registries.rs +++ b/cli/lsp/registries.rs @@ -266,6 +266,7 @@ impl Default for ModuleRegistry { true, None, BlobStore::default(), + None, ) .unwrap(); @@ -285,6 +286,7 @@ impl ModuleRegistry { true, None, BlobStore::default(), + None, ) .context("Error creating file fetcher in module registry.") .unwrap(); diff --git a/cli/main.rs b/cli/main.rs index 77cce1d05..93b3d5021 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -109,6 +109,10 @@ fn create_web_worker_callback( .log_level .map_or(false, |l| l == log::Level::Debug), unstable: program_state.flags.unstable, + unsafely_treat_insecure_origin_as_secure: program_state + .flags + .unsafely_treat_insecure_origin_as_secure + .clone(), root_cert_store: program_state.root_cert_store.clone(), user_agent: version::get_user_agent(), seed: program_state.flags.seed, @@ -189,6 +193,10 @@ pub fn create_main_worker( .log_level .map_or(false, |l| l == log::Level::Debug), unstable: program_state.flags.unstable, + unsafely_treat_insecure_origin_as_secure: program_state + .flags + .unsafely_treat_insecure_origin_as_secure + .clone(), root_cert_store: program_state.root_cert_store.clone(), user_agent: version::get_user_agent(), seed: program_state.flags.seed, diff --git a/cli/program_state.rs b/cli/program_state.rs index 244351a03..721ccda9c 100644 --- a/cli/program_state.rs +++ b/cli/program_state.rs @@ -1,5 +1,6 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +use crate::colors; use crate::config_file::ConfigFile; use crate::deno_dir; use crate::file_fetcher::CacheSetting; @@ -117,6 +118,21 @@ impl ProgramState { } } + if let Some(insecure_allowlist) = + flags.unsafely_treat_insecure_origin_as_secure.as_ref() + { + let domains = if insecure_allowlist.is_empty() { + "for all domains".to_string() + } else { + format!("for: {}", insecure_allowlist.join(", ")) + }; + let msg = format!( + "DANGER: SSL ceritificate validation is disabled {}", + domains + ); + eprintln!("{}", colors::yellow(msg)); + } + let cache_usage = if flags.cached_only { CacheSetting::Only } else if !flags.cache_blocklist.is_empty() { @@ -137,6 +153,7 @@ impl ProgramState { !flags.no_remote, Some(root_cert_store.clone()), blob_store.clone(), + flags.unsafely_treat_insecure_origin_as_secure.clone(), )?; let lockfile = if let Some(filename) = &flags.lock { diff --git a/cli/specifier_handler.rs b/cli/specifier_handler.rs index 5fd9d6b25..ddc3adc7e 100644 --- a/cli/specifier_handler.rs +++ b/cli/specifier_handler.rs @@ -598,6 +598,7 @@ pub mod tests { true, None, BlobStore::default(), + None, ) .expect("could not setup"); let disk_cache = deno_dir.gen_cache; diff --git a/cli/standalone.rs b/cli/standalone.rs index 460ee23d0..ded3c88e8 100644 --- a/cli/standalone.rs +++ b/cli/standalone.rs @@ -57,6 +57,7 @@ pub struct Metadata { pub log_level: Option, pub ca_stores: Option>, pub ca_data: Option>, + pub unsafely_treat_insecure_origin_as_secure: Option>, } pub const MAGIC_TRAILER: &[u8; 8] = b"d3n0l4nd"; @@ -252,6 +253,8 @@ pub async fn run( debug_flag: metadata.log_level.map_or(false, |l| l == log::Level::Debug), user_agent: version::get_user_agent(), unstable: metadata.unstable, + unsafely_treat_insecure_origin_as_secure: metadata + .unsafely_treat_insecure_origin_as_secure, root_cert_store: Some(root_cert_store), seed: metadata.seed, js_error_create_fn: None, diff --git a/cli/tests/cafile_ts_fetch_unsafe_ssl.ts.out b/cli/tests/cafile_ts_fetch_unsafe_ssl.ts.out new file mode 100644 index 000000000..f0b63833a --- /dev/null +++ b/cli/tests/cafile_ts_fetch_unsafe_ssl.ts.out @@ -0,0 +1,2 @@ +DANGER: SSL ceritificate validation is disabled for all domains +Hello diff --git a/cli/tests/cafile_url_imports_unsafe_ssl.ts.out b/cli/tests/cafile_url_imports_unsafe_ssl.ts.out new file mode 100644 index 000000000..3f6a0c07f --- /dev/null +++ b/cli/tests/cafile_url_imports_unsafe_ssl.ts.out @@ -0,0 +1,3 @@ +DANGER: SSL ceritificate validation is disabled for: localhost +Hello +success diff --git a/cli/tests/integration/mod.rs b/cli/tests/integration/mod.rs index cc016382f..938d40125 100644 --- a/cli/tests/integration/mod.rs +++ b/cli/tests/integration/mod.rs @@ -474,6 +474,19 @@ fn broken_stdout() { // http_server: true, // }); +itest!(cafile_url_imports_unsafe_ssl { + args: "run --quiet --reload --unsafely-treat-insecure-origin-as-secure=localhost cafile_url_imports.ts", + output: "cafile_url_imports_unsafe_ssl.ts.out", + http_server: true, +}); + +itest!(cafile_ts_fetch_unsafe_ssl { + args: + "run --quiet --reload --allow-net --unsafely-treat-insecure-origin-as-secure cafile_ts_fetch.ts", + output: "cafile_ts_fetch_unsafe_ssl.ts.out", + http_server: true, +}); + #[test] #[ignore] fn cafile_env_fetch() { diff --git a/cli/tools/standalone.rs b/cli/tools/standalone.rs index 46ac27b83..2eaf50161 100644 --- a/cli/tools/standalone.rs +++ b/cli/tools/standalone.rs @@ -99,6 +99,9 @@ pub fn create_standalone_binary( location: flags.location.clone(), permissions: flags.clone().into(), v8_flags: flags.v8_flags.clone(), + unsafely_treat_insecure_origin_as_secure: flags + .unsafely_treat_insecure_origin_as_secure + .clone(), log_level: flags.log_level, ca_stores: flags.ca_stores, ca_data, @@ -223,6 +226,8 @@ pub fn compile_to_runtime_flags( lock: None, log_level: flags.log_level, no_check: false, + unsafely_treat_insecure_origin_as_secure: flags + .unsafely_treat_insecure_origin_as_secure, no_remote: false, prompt: flags.prompt, reload: false, -- cgit v1.2.3