From 4b433c25e616af4c9a167dd068bba56c34546712 Mon Sep 17 00:00:00 2001 From: orangels Date: Wed, 6 May 2026 20:13:02 +0800 Subject: [PATCH] fix: redact config tokens in debug output --- src/config.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index 199fe47..722b944 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,7 @@ use regex::Regex; use serde::Deserialize; use std::collections::HashMap; +use std::fmt; use std::path::{Path, PathBuf}; use thiserror::Error; @@ -33,7 +34,7 @@ pub enum ProtocolKind { Anthropic, } -#[derive(Debug, Deserialize)] +#[derive(Deserialize)] pub struct ProviderConfig { pub protocol: ProtocolKind, pub base_url: String, @@ -41,6 +42,18 @@ pub struct ProviderConfig { pub default_model: String, } +impl fmt::Debug for ProviderConfig { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("ProviderConfig") + .field("protocol", &self.protocol) + .field("base_url", &self.base_url) + .field("api_token", &"") + .field("default_model", &self.default_model) + .finish() + } +} + #[derive(Debug, Deserialize)] pub struct BenchmarkConfig { #[serde(default = "default_benchmark_data_dir")] @@ -67,7 +80,7 @@ pub struct DatasetConfig { pub split: String, } -#[derive(Debug, Deserialize)] +#[derive(Deserialize)] pub struct AppConfig { #[serde(default)] pub default_provider: Option, @@ -76,6 +89,17 @@ pub struct AppConfig { pub benchmarks: BenchmarkConfig, } +impl fmt::Debug for AppConfig { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("AppConfig") + .field("default_provider", &self.default_provider) + .field("providers", &self.providers) + .field("benchmarks", &self.benchmarks) + .finish() + } +} + impl AppConfig { pub fn load(path: &Path) -> Result { let contents = std::fs::read_to_string(path).map_err(|source| ConfigError::Read { @@ -268,4 +292,29 @@ providers: assert_eq!(provider.protocol, ProtocolKind::Anthropic); assert_eq!(config.benchmarks.data_dir, "data/benchmarks"); } + + #[test] + fn debug_redacts_provider_tokens() { + let config = AppConfig::load_from_str_with_env( + r#" +default_provider: openai +providers: + openai: + protocol: openai + base_url: https://api.openai.test/v1 + api_token: ${LQ_TEST_TOKEN} + default_model: gpt-test +"#, + |name| match name { + "LQ_TEST_TOKEN" => Ok("super-secret-token".to_string()), + _ => Err(()), + }, + ) + .expect("load config"); + + let debug = format!("{config:?}"); + + assert!(!debug.contains("super-secret-token")); + assert!(debug.contains("")); + } }