mirror of
https://github.com/openai/codex.git
synced 2026-11-14 21:40:39 +00:00
Harden credential handling in shell snapshots and replay (#44040)
## Why Shell quoting can hide credentials from raw-text checks, and startup files can restore real credentials after the broker replaces them with dummy values. ## What changed - Decode shell literals without evaluating them and reject snapshots containing credentials in executable source, including aliases, functions, and heredocs. - Preserve credential policy overrides, explicit unsets, and aliases whose source variables were removed. Support credential aliases in Zsh tied arrays while rejecting credentials that span array elements. - Guard snapshot replay against credential restoration through shell startup files and preserve unrelated `ENV` settings. - Apply Windows environment-key casing rules to credential overrides, suppress unredacted sandbox diagnostics during snapshot capture, and clear inherited environment variables before launching escalated commands. ## Testing Add regression coverage for shell quoting and escaped credentials, Zsh tied arrays, startup-file replay, readonly credentials, policy overrides, and sensitive capture timeout and cancellation handling. GitOrigin-RevId: 58274c07c715423241d26ce6dd2c2b4230cf0f64
This commit is contained in:
@@ -32,8 +32,20 @@ pub(super) enum ValuePart {
|
||||
|
||||
pub(super) enum Export<'a> {
|
||||
Captured(&'a str),
|
||||
Alias { key: &'a str, value: Value },
|
||||
Assignment { declaration: &'a str, value: Value },
|
||||
Assignment {
|
||||
declaration: &'a str,
|
||||
value: Value,
|
||||
},
|
||||
Array {
|
||||
prefix: &'a str,
|
||||
elements: Vec<Value>,
|
||||
suffix: &'a str,
|
||||
},
|
||||
ArrayBinding {
|
||||
key: &'a str,
|
||||
declaration: &'a str,
|
||||
suffix: &'a str,
|
||||
},
|
||||
}
|
||||
|
||||
impl Value {
|
||||
@@ -64,12 +76,30 @@ pub(super) fn render(state: &str, aliases: &str, exports: &[Export<'_>]) -> Opti
|
||||
for export in exports {
|
||||
match export {
|
||||
Export::Captured(source) => output.push_str(source),
|
||||
Export::Alias { key, value } => {
|
||||
output.push_str(&format!("export {key}={}\n", value.render()?));
|
||||
}
|
||||
Export::Assignment { declaration, value } => {
|
||||
output.push_str(&format!("{declaration}={}\n", value.render()?));
|
||||
}
|
||||
Export::Array {
|
||||
prefix,
|
||||
elements,
|
||||
suffix,
|
||||
} => {
|
||||
let elements = elements
|
||||
.iter()
|
||||
.map(Value::render)
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
output.push_str(&format!("{prefix}({}){suffix}", elements.join(" ")));
|
||||
}
|
||||
Export::ArrayBinding {
|
||||
key,
|
||||
declaration,
|
||||
suffix,
|
||||
} => {
|
||||
output.push_str(&format!(
|
||||
"if [ \"${{{key}+x}}\" = x ]; then\n{declaration}{}\nfi\n",
|
||||
suffix.trim_end()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(output)
|
||||
|
||||
Reference in New Issue
Block a user