summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock5
-rw-r--r--Cargo.toml1
-rw-r--r--cli/Cargo.toml2
-rw-r--r--cli/tests/integration/run_tests.rs45
-rw-r--r--runtime/Cargo.toml1
-rw-r--r--runtime/permissions/prompter.rs16
6 files changed, 65 insertions, 5 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3233b03c9..97d27d34c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -525,9 +525,9 @@ dependencies = [
[[package]]
name = "console_static_text"
-version = "0.3.4"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f166cdfb9db0607e2079b382ba64bc4164344006c733b95c1ecfa782a180a34a"
+checksum = "953d2c3cf53213a4eccdbe8f2e0b49b5d0f77e87a2a9060117bbf9346f92b64e"
dependencies = [
"unicode-width",
"vte",
@@ -1285,6 +1285,7 @@ name = "deno_runtime"
version = "0.99.0"
dependencies = [
"atty",
+ "console_static_text",
"deno_ast",
"deno_broadcast_channel",
"deno_cache",
diff --git a/Cargo.toml b/Cargo.toml
index da026daf1..2e9d34b85 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -84,6 +84,7 @@ base64 = "=0.13.1"
bencher = "0.1"
bytes = "=1.2.1"
cache_control = "=0.2.0"
+console_static_text = "=0.7.1"
data-url = "=0.2.0"
dlopen = "0.1.8"
encoding_rs = "=0.8.31"
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 65e4359c2..27409ec91 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -62,7 +62,7 @@ chrono = { version = "=0.4.22", default-features = false, features = ["clock"] }
clap = "=3.1.12"
clap_complete = "=3.1.2"
clap_complete_fig = "=3.1.5"
-console_static_text = "=0.3.4"
+console_static_text.workspace = true
data-url.workspace = true
dissimilar = "=1.0.4"
dprint-plugin-json = "=0.17.0"
diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs
index 239311975..c3a2c45a7 100644
--- a/cli/tests/integration/run_tests.rs
+++ b/cli/tests/integration/run_tests.rs
@@ -4027,6 +4027,51 @@ fn stdio_streams_are_locked_in_permission_prompt() {
});
}
+#[test]
+fn permission_prompt_strips_ansi_codes_and_control_chars() {
+ let _guard = util::http_server();
+ util::with_pty(&["repl"], |mut console| {
+ console.write_line(
+ r#"Deno.permissions.request({ name: "env", variable: "\rDo you like ice cream? y/n" });"#
+ );
+ console.write_line("close();");
+ let output = console.read_all_output();
+
+ assert!(output.contains(
+ "┌ ⚠️ Deno requests env access to \"Do you like ice cream? y/n\"."
+ ));
+ });
+
+ util::with_pty(&["repl"], |mut console| {
+ console.write_line(
+ r#"
+const boldANSI = "\u001b[1m" // bold
+const unboldANSI = "\u001b[22m" // unbold
+
+const prompt = `┌ ⚠️ ${boldANSI}Deno requests run access to "echo"${unboldANSI}
+├ Requested by \`Deno.Command().output()`
+
+const moveANSIUp = "\u001b[1A" // moves to the start of the line
+const clearANSI = "\u001b[2K" // clears the line
+const moveANSIStart = "\u001b[1000D" // moves to the start of the line
+
+Deno[Object.getOwnPropertySymbols(Deno)[0]].core.ops.op_spawn_child({
+ cmd: "cat",
+ args: ["/etc/passwd"],
+ clearEnv: false,
+ env: [],
+ stdin: "null",
+ stdout: "inherit",
+ stderr: "piped"
+}, moveANSIUp + clearANSI + moveANSIStart + prompt)"#,
+ );
+ console.write_line("close();");
+ let output = console.read_all_output();
+
+ assert!(output.contains(r#"┌ ⚠️ Deno requests run access to "cat""#));
+ });
+}
+
itest!(node_builtin_modules_ts {
args: "run --quiet --allow-read run/node_builtin_modules/mod.ts hello there",
output: "run/node_builtin_modules/mod.ts.out",
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index 0ba8f8d3a..360ef2aa0 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -86,6 +86,7 @@ deno_websocket.workspace = true
deno_webstorage.workspace = true
atty.workspace = true
+console_static_text.workspace = true
dlopen.workspace = true
encoding_rs.workspace = true
filetime = "0.2.16"
diff --git a/runtime/permissions/prompter.rs b/runtime/permissions/prompter.rs
index d148b485e..d94264b1a 100644
--- a/runtime/permissions/prompter.rs
+++ b/runtime/permissions/prompter.rs
@@ -5,6 +5,14 @@ use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex;
use once_cell::sync::Lazy;
+/// Helper function to strip ansi codes and ASCII control characters.
+fn strip_ansi_codes_and_ascii_control(s: &str) -> std::borrow::Cow<str> {
+ console_static_text::strip_ansi_codes(s)
+ .chars()
+ .filter(|c| !c.is_ascii_control())
+ .collect()
+}
+
pub const PERMISSION_EMOJI: &str = "⚠️";
#[derive(Debug, Eq, PartialEq)]
@@ -203,6 +211,10 @@ impl PermissionPrompter for TtyPrompter {
let _stdout_guard = std::io::stdout().lock();
let _stderr_guard = std::io::stderr().lock();
+ let message = strip_ansi_codes_and_ascii_control(message);
+ let name = strip_ansi_codes_and_ascii_control(name);
+ let api_name = api_name.map(strip_ansi_codes_and_ascii_control);
+
// print to stderr so that if stdout is piped this is still displayed.
let opts: String = if is_unary {
format!("[y/n/A] (y = yes, allow; n = no, deny; A = allow all {name} permissions)")
@@ -211,9 +223,9 @@ impl PermissionPrompter for TtyPrompter {
};
eprint!("┌ {PERMISSION_EMOJI} ");
eprint!("{}", colors::bold("Deno requests "));
- eprint!("{}", colors::bold(message));
+ eprint!("{}", colors::bold(message.clone()));
eprintln!("{}", colors::bold("."));
- if let Some(api_name) = api_name {
+ if let Some(api_name) = api_name.clone() {
eprintln!("├ Requested by `{api_name}` API");
}
let msg = format!("Run again with --allow-{name} to bypass this prompt.");