const SECRET_NEEDLES: &[&str] = &[
"-----BEGIN",
"Bearer ",
"bearer ",
"AKIA", "ASIA", "ghp_", "gho_", "ghs_", "github_pat_", "xoxb-", "xoxp-", "xoxa-", "sk-live-", "sk_test_", "sk_live_", "AIza", "ya29.", "sk-ant-api", ];
const SECRET_KEY_MARKERS: &[&str] = &[
"token",
"secret",
"password",
"passwd",
"apikey",
"api_key",
"credential",
"authorization",
];
const REDACTED: &str = "[redacted]";
pub const ENVELOPE_SECRET_KEY_NAMES: &[&str] = &[
"accesstoken",
"apitoken",
"apikey",
"authheader",
"authorization",
"authtoken",
"bearertoken",
"clientsecret",
"cookie",
"credential",
"credentials",
"idtoken",
"password",
"passwd",
"privatekey",
"refreshtoken",
"secret",
"secretkey",
"setcookie",
"token",
];
fn normalize_key_name(key: &str) -> String {
key.chars()
.filter(|c| !matches!(c, '-' | '_' | '.' | ':' | ' '))
.flat_map(char::to_lowercase)
.collect()
}
pub fn scrub_envelope_keys(v: &mut Value) -> usize {
match v {
Value::Object(map) => {
let mut count = 0;
for (key, val) in map.iter_mut() {
if ENVELOPE_SECRET_KEY_NAMES.contains(&normalize_key_name(key).as_str()) {
*val = Value::String(REDACTED.to_string());
count += 1;
} else {
count += scrub_envelope_keys(val);
}
}
count
}
Value::Array(items) => items.iter_mut().map(scrub_envelope_keys).sum(),
_ => 0,
}
}