From edceb7284f895539fdd71533c1e59c31c4b7940e Mon Sep 17 00:00:00 2001 From: Peter Tripp Date: Wed, 23 Jul 2025 16:55:13 -0400 Subject: [PATCH] Redact secrets from environment in LSP Server Info (#34971) In "Server Info" view of LSP logs: - Redacts sensitive values from environment - Sorts environment by name | Before | After | | - | - | | Screenshot 2025-07-23 at 14 10 14 | image | Release Notes: - Improved display of environment variables in LSP Logs: Server Info view --- crates/lsp/src/lsp.rs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 7dcfa61f47..a820aaf748 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -4,7 +4,7 @@ pub use lsp_types::request::*; pub use lsp_types::*; use anyhow::{Context as _, Result, anyhow}; -use collections::HashMap; +use collections::{BTreeMap, HashMap}; use futures::{ AsyncRead, AsyncWrite, Future, FutureExt, channel::oneshot::{self, Canceled}, @@ -40,7 +40,7 @@ use std::{ time::{Duration, Instant}, }; use std::{path::Path, process::Stdio}; -use util::{ConnectionResult, ResultExt, TryFutureExt}; +use util::{ConnectionResult, ResultExt, TryFutureExt, redact}; const JSON_RPC_VERSION: &str = "2.0"; const CONTENT_LEN_HEADER: &str = "Content-Length: "; @@ -62,7 +62,7 @@ pub enum IoKind { /// Represents a launchable language server. This can either be a standalone binary or the path /// to a runtime with arguments to instruct it to launch the actual language server file. -#[derive(Debug, Clone, Deserialize)] +#[derive(Clone, Deserialize)] pub struct LanguageServerBinary { pub path: PathBuf, pub arguments: Vec, @@ -1448,6 +1448,33 @@ impl fmt::Debug for LanguageServer { } } +impl fmt::Debug for LanguageServerBinary { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut debug = f.debug_struct("LanguageServerBinary"); + debug.field("path", &self.path); + debug.field("arguments", &self.arguments); + + if let Some(env) = &self.env { + let redacted_env: BTreeMap = env + .iter() + .map(|(key, value)| { + let redacted_value = if redact::should_redact(key) { + "REDACTED".to_string() + } else { + value.clone() + }; + (key.clone(), redacted_value) + }) + .collect(); + debug.field("env", &Some(redacted_env)); + } else { + debug.field("env", &self.env); + } + + debug.finish() + } +} + impl Drop for Subscription { fn drop(&mut self) { match self {