Change summary
crates/project/src/lsp_store.rs | 8 ++++++--
crates/util/src/redact.rs | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 2 deletions(-)
Detailed changes
@@ -128,6 +128,7 @@ use util::{
ConnectionResult, ResultExt as _, debug_panic, defer, maybe, merge_json_value_into,
paths::{PathStyle, SanitizedPath},
post_inc,
+ redact::redact_command,
rel_path::RelPath,
};
@@ -577,9 +578,12 @@ impl LocalLspStore {
},
},
);
- log::error!("Failed to start language server {server_name:?}: {err:?}");
+ log::error!(
+ "Failed to start language server {server_name:?}: {}",
+ redact_command(&format!("{err:?}"))
+ );
if !log.is_empty() {
- log::error!("server stderr: {log}");
+ log::error!("server stderr: {}", redact_command(&log));
}
None
}
@@ -1,3 +1,9 @@
+use std::sync::LazyLock;
+
+static REDACT_REGEX: LazyLock<regex::Regex> = LazyLock::new(|| {
+ regex::Regex::new(r#"([A-Z_][A-Z0-9_]*)=("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\S+)"#).unwrap()
+});
+
/// Whether a given environment variable name should have its value redacted
pub fn should_redact(env_var_name: &str) -> bool {
const REDACTED_SUFFIXES: &[&str] = &[
@@ -13,3 +19,31 @@ pub fn should_redact(env_var_name: &str) -> bool {
.iter()
.any(|suffix| env_var_name.ends_with(suffix))
}
+
+/// Redact a string which could include a command with environment variables
+pub fn redact_command(command: &str) -> String {
+ REDACT_REGEX
+ .replace_all(command, |caps: ®ex::Captures| {
+ let var_name = &caps[1];
+ let value = &caps[2];
+ if should_redact(var_name) {
+ format!(r#"{}="[REDACTED]""#, var_name)
+ } else {
+ format!("{}={}", var_name, value)
+ }
+ })
+ .to_string()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_redact_string_with_multiple_env_vars() {
+ let input = r#"failed to spawn command cd "/code/something" && ANTHROPIC_API_KEY="sk-ant-api03-WOOOO" COMMAND_MODE="unix2003" GEMINI_API_KEY="AIGEMINIFACE" HOME="/Users/foo""#;
+ let result = redact_command(input);
+ let expected = r#"failed to spawn command cd "/code/something" && ANTHROPIC_API_KEY="[REDACTED]" COMMAND_MODE="unix2003" GEMINI_API_KEY="[REDACTED]" HOME="/Users/foo""#;
+ assert_eq!(result, expected);
+ }
+}