From 413f4ea49c993ed531c32a4743c07850dda2f63f Mon Sep 17 00:00:00 2001 From: Peter Tripp Date: Thu, 18 Dec 2025 14:05:14 -0500 Subject: [PATCH] Redact environment variables from language server spawn errors (#44783) Redact environment variables from zed logs when lsp fails to spawn. Release Notes: - N/A --- crates/project/src/lsp_store.rs | 8 ++++++-- crates/util/src/redact.rs | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index 6696ec8c4c280199a55d098ab63a321f126eea5e..5093b6977a1bffe82339ede00d2e6e4b4b14b4c1 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -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 } diff --git a/crates/util/src/redact.rs b/crates/util/src/redact.rs index 6b297dfb58bb0b4537d4032d8f9cf4db845f9d78..ad11f7618b1cf57c27e7367845cf66e9d0e6bd0b 100644 --- a/crates/util/src/redact.rs +++ b/crates/util/src/redact.rs @@ -1,3 +1,9 @@ +use std::sync::LazyLock; + +static REDACT_REGEX: LazyLock = 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); + } +}