Unwrap double-quoted Codex Bash commands
This commit is contained in:
1 parent
26fe9895e7
commit
cbdd8493ed
1 file changed
+40
-3
@@ -291,13 +291,16 @@ fn command_tool(item: &Value) -> (String, Value) {
|
||||
("Shell".to_string(), json!({"command": command}))
|
||||
}
|
||||
|
||||
/// App-server renders the executor argv into one shell-quoted string. Unwrap only the exact Bash
|
||||
/// form Codex currently emits; anything with another argument or quoting form stays visible rather
|
||||
/// than being decoded into a command that was not actually run.
|
||||
/// App-server renders the executor argv into one shell-quoted string. Unwrap only an exact Bash
|
||||
/// invocation containing one shell word; extra arguments stay visible rather than being decoded
|
||||
/// into a command that was not actually run.
|
||||
fn rendered_bash_script(command: &str) -> Option<String> {
|
||||
let quoted = ["/usr/bin/bash -lc ", "/bin/bash -lc ", "bash -lc "]
|
||||
.iter()
|
||||
.find_map(|prefix| command.strip_prefix(prefix))?;
|
||||
if quoted.starts_with('"') {
|
||||
return double_quoted_shell_word(quoted);
|
||||
}
|
||||
if !quoted.starts_with('\'') {
|
||||
return (!quoted.is_empty() && !quoted.chars().any(char::is_whitespace))
|
||||
.then(|| quoted.to_string());
|
||||
@@ -324,6 +327,26 @@ fn rendered_bash_script(command: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn double_quoted_shell_word(quoted: &str) -> Option<String> {
|
||||
let mut chars = quoted.strip_prefix('"')?.chars();
|
||||
let mut script = String::new();
|
||||
while let Some(character) = chars.next() {
|
||||
match character {
|
||||
'"' => return chars.next().is_none().then_some(script),
|
||||
'\\' => match chars.next()? {
|
||||
escaped @ ('$' | '`' | '"' | '\\') => script.push(escaped),
|
||||
'\n' => {}
|
||||
escaped => {
|
||||
script.push('\\');
|
||||
script.push(escaped);
|
||||
}
|
||||
},
|
||||
character => script.push(character),
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn shell_word(word: &Value) -> String {
|
||||
let Some(word) = word.as_str() else {
|
||||
return word.to_string();
|
||||
@@ -587,6 +610,20 @@ mod tests {
|
||||
))
|
||||
);
|
||||
|
||||
let double_quoted = tool(&json!({
|
||||
"id": "double-quoted",
|
||||
"type": "commandExecution",
|
||||
"command": r#"/usr/bin/bash -lc "printf '%s\\n' \"\$HOME\" \\path""#
|
||||
}));
|
||||
assert_eq!(
|
||||
double_quoted,
|
||||
Some((
|
||||
"double-quoted".to_string(),
|
||||
"Bash".to_string(),
|
||||
json!({"command": "printf '%s\\n' \"$HOME\" \\path"})
|
||||
))
|
||||
);
|
||||
|
||||
let fish = tool(&line(
|
||||
r#"{"id":"fish","type":"commandExecution","command":["/usr/bin/fish","-c","pwd"]}"#,
|
||||
));
|
||||
|
||||
Reference in new issue
Block a user