diff --git a/crates/context_server/src/context_server.rs b/crates/context_server/src/context_server.rs index 387235307a..f774deef17 100644 --- a/crates/context_server/src/context_server.rs +++ b/crates/context_server/src/context_server.rs @@ -16,6 +16,7 @@ use gpui::AsyncApp; use parking_lot::RwLock; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use util::redact::should_redact; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ContextServerId(pub Arc); @@ -26,13 +27,29 @@ impl Display for ContextServerId { } } -#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, Debug)] +#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema)] pub struct ContextServerCommand { pub path: String, pub args: Vec, pub env: Option>, } +impl std::fmt::Debug for ContextServerCommand { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let filtered_env = self.env.as_ref().map(|env| { + env.iter() + .map(|(k, v)| (k, if should_redact(k) { "[REDACTED]" } else { v })) + .collect::>() + }); + + f.debug_struct("ContextServerCommand") + .field("path", &self.path) + .field("args", &self.args) + .field("env", &filtered_env) + .finish() + } +} + enum ContextServerTransport { Stdio(ContextServerCommand), Custom(Arc), diff --git a/crates/extension/src/types.rs b/crates/extension/src/types.rs index 31feeb1f91..cb24e5077b 100644 --- a/crates/extension/src/types.rs +++ b/crates/extension/src/types.rs @@ -5,6 +5,8 @@ mod slash_command; use std::ops::Range; +use util::redact::should_redact; + pub use context_server::*; pub use dap::*; pub use lsp::*; @@ -14,7 +16,6 @@ pub use slash_command::*; pub type EnvVars = Vec<(String, String)>; /// A command. -#[derive(Debug)] pub struct Command { /// The command to execute. pub command: String, @@ -24,6 +25,22 @@ pub struct Command { pub env: EnvVars, } +impl std::fmt::Debug for Command { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let filtered_env = self + .env + .iter() + .map(|(k, v)| (k, if should_redact(k) { "[REDACTED]" } else { v })) + .collect::>(); + + f.debug_struct("Command") + .field("command", &self.command) + .field("args", &self.args) + .field("env", &filtered_env) + .finish() + } +} + /// A label containing some code. #[derive(Debug, Clone)] pub struct CodeLabel { diff --git a/crates/util/src/redact.rs b/crates/util/src/redact.rs new file mode 100644 index 0000000000..0b979fb413 --- /dev/null +++ b/crates/util/src/redact.rs @@ -0,0 +1,8 @@ +/// Whether a given environment variable name should have its value redacted +pub fn should_redact(env_var_name: &str) -> bool { + const REDACTED_SUFFIXES: &[&str] = + &["KEY", "TOKEN", "PASSWORD", "SECRET", "PASS", "CREDENTIALS"]; + REDACTED_SUFFIXES + .iter() + .any(|suffix| env_var_name.ends_with(suffix)) +} diff --git a/crates/util/src/util.rs b/crates/util/src/util.rs index 79137208ea..eb07d3e5e5 100644 --- a/crates/util/src/util.rs +++ b/crates/util/src/util.rs @@ -4,6 +4,7 @@ pub mod command; pub mod fs; pub mod markdown; pub mod paths; +pub mod redact; pub mod serde; pub mod shell_env; pub mod size;