fix: separate sensitive environment to prevent log leaks

This commit is contained in:
Nolan Darilek
2026-08-24 16:38:57 +03:00
committed by Lars Wirzenius
parent ade641d76d
commit c7666c3246
2 changed files with 33 additions and 3 deletions
+32 -2
View File
@@ -84,6 +84,7 @@ impl Adapters {
pub struct Adapter {
bin: PathBuf,
env: HashMap<String, String>,
sensitive_env: HashMap<String, Sensitive>,
config: HashMap<String, serde_norway::Value>,
config_env: Option<String>,
}
@@ -106,7 +107,7 @@ impl Adapter {
pub fn with_sensitive_environment(mut self, env: &HashMap<String, Sensitive>) -> Self {
for (key, value) in env.iter() {
self.env.insert(key.into(), value.as_str().into());
self.sensitive_env.insert(key.into(), value.clone());
}
self
}
@@ -133,7 +134,14 @@ impl Adapter {
}
fn envs(&self) -> impl Iterator<Item = (&OsStr, &OsStr)> {
self.env.iter().map(|(k, v)| (k.as_ref(), v.as_ref()))
self.env
.iter()
.map(|(k, v)| (k.as_ref(), v.as_ref()))
.chain(
self.sensitive_env
.iter()
.map(|(k, v)| (k.as_ref(), v.as_str().as_ref())),
)
}
#[allow(clippy::too_many_arguments)]
@@ -987,6 +995,28 @@ echo '{"response":"finished","result":"success"}'
Ok(())
}
#[test]
fn adapter_redacts_sensitive_environment() -> TestResult<()> {
let sensitive: HashMap<String, Sensitive> =
serde_norway::from_str("SECRET_TOKEN: hunter2")?;
let adapter = Adapter::new(Path::new("/bin/true"))
.with_environment(&HashMap::from([("PLAIN".into(), "visible".into())]))
.with_sensitive_environment(&sensitive);
let debugged = format!("{adapter:?}");
assert!(debugged.contains("SECRET_TOKEN"));
assert!(!debugged.contains("hunter2"));
let json = serde_json::to_string(&adapter)?;
assert!(!json.contains("hunter2"));
let envs: Vec<_> = adapter.envs().collect();
assert!(envs.contains(&("SECRET_TOKEN".as_ref(), "hunter2".as_ref())));
assert!(envs.contains(&("PLAIN".as_ref(), "visible".as_ref())));
Ok(())
}
#[test]
fn adapter_has_bad_interpreter() -> TestResult<()> {
// We test this with a shebang. However, the same kind of code
+1 -1
View File
@@ -24,7 +24,7 @@ const PLACEHOLDER: &str = "<REDACTED>";
/// Hold a sensitive string, such as a password or an API token. The
/// value can be accessed ([`Sensitive::as_str`]), but won't be
/// printed, even in debug output, and won't be serialized by `serde`.
#[derive()]
#[derive(Clone, Eq, PartialEq)]
pub struct Sensitive {
#[allow(dead_code)]
//#[serde(serialize_with = "serialize")]