From c4289909005f71a319c4d191a37644f242aca512 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Wed, 11 Mar 2026 12:55:28 -0600 Subject: [PATCH] fix: the updated regex for secrets injection broke MCP server secrets interpolation because the regex greedily matched on new lines, replacing too much content. This fix just ignores commented out lines in YAML files by skipping commented out lines. --- src/vault/mod.rs | 2 +- src/vault/utils.rs | 33 ++++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/vault/mod.rs b/src/vault/mod.rs index 83db5af..e170075 100644 --- a/src/vault/mod.rs +++ b/src/vault/mod.rs @@ -15,7 +15,7 @@ use inquire::{Password, PasswordDisplayMode, required}; use std::sync::{Arc, LazyLock}; use tokio::runtime::Handle; -pub static SECRET_RE: LazyLock = LazyLock::new(|| Regex::new(r"^[^#]*\{\{(.+)}}").unwrap()); +pub static SECRET_RE: LazyLock = LazyLock::new(|| Regex::new(r"\{\{(.+)}}").unwrap()); #[derive(Debug, Default, Clone)] pub struct Vault { diff --git a/src/vault/utils.rs b/src/vault/utils.rs index 1a81003..50d0cae 100644 --- a/src/vault/utils.rs +++ b/src/vault/utils.rs @@ -6,7 +6,6 @@ use gman::providers::local::LocalProvider; use indoc::formatdoc; use inquire::validator::Validation; use inquire::{Confirm, Password, PasswordDisplayMode, Text, min_length, required}; -use std::borrow::Cow; use std::path::PathBuf; pub fn ensure_password_file_initialized(local_provider: &mut LocalProvider) -> Result<()> { @@ -166,18 +165,30 @@ pub fn create_vault_password_file(vault: &mut Vault) -> Result<()> { Ok(()) } -pub fn interpolate_secrets<'a>(content: &'a str, vault: &Vault) -> (Cow<'a, str>, Vec) { +pub fn interpolate_secrets(content: &str, vault: &Vault) -> (String, Vec) { let mut missing_secrets = vec![]; - let parsed_content = SECRET_RE.replace_all(content, |caps: &fancy_regex::Captures<'_>| { - let secret = vault.get_secret(caps[1].trim(), false); - match secret { - Ok(s) => s, - Err(_) => { - missing_secrets.push(caps[1].to_string()); - "".to_string() + let parsed_content: String = content + .lines() + .map(|line| { + if line.trim_start().starts_with('#') { + return line.to_string(); } - } - }); + + SECRET_RE + .replace_all(line, |caps: &fancy_regex::Captures<'_>| { + let secret = vault.get_secret(caps[1].trim(), false); + match secret { + Ok(s) => s, + Err(_) => { + missing_secrets.push(caps[1].to_string()); + "".to_string() + } + } + }) + .to_string() + }) + .collect::>() + .join("\n"); (parsed_content, missing_secrets) }