mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Redact secrets from app-server command execution items (#36893)
## Why Client-facing command execution items can include recognizable secrets in the rendered command or parsed command actions. ## What changed - Redact secrets in `commandExecution.command` and `commandActions` for live items, completed items, and replayed thread history. - Keep command approval requests backed by the original executable command and parsed actions while using the redacted representation for display items. - Document that execution item commands are redacted display values rather than executable commands. ## Testing - Cover redaction for command conversion, parsed search actions, legacy replay, approval flows, completion notifications, and rejected commands. GitOrigin-RevId: 2ad056f21882bf5166182ad1a4ff0bf6471d9c0e
This commit is contained in:
1 parent
6d4d9442c7
commit
fcf636a41d
10 files changed
+238
-70
No files matched your search
@@ -10,7 +10,7 @@ use super::UserInput;
|
||||
use super::shared::v2_enum_from_core;
|
||||
use crate::JsonSchema;
|
||||
use crate::TS;
|
||||
use crate::protocol::item_builders::command_actions_for_path_uri;
|
||||
use crate::protocol::item_builders::CommandExecutionPresentation;
|
||||
use crate::protocol::item_builders::convert_patch_changes;
|
||||
use crate::protocol::item_builders::review_output_text;
|
||||
use codex_experimental_api_macros::ExperimentalApi;
|
||||
@@ -43,7 +43,6 @@ use codex_protocol::protocol::GuardianUserAuthorization as CoreGuardianUserAutho
|
||||
use codex_protocol::protocol::PatchApplyStatus as CorePatchApplyStatus;
|
||||
use codex_protocol::protocol::ReviewDecision as CoreReviewDecision;
|
||||
use codex_protocol::protocol::SubAgentActivityKind as CoreSubAgentActivityKind;
|
||||
use codex_shell_command::parse_command::shlex_join;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_path_uri::LegacyAppPathString;
|
||||
use serde::Deserialize;
|
||||
@@ -841,24 +840,31 @@ impl From<CoreTurnItem> for ThreadItem {
|
||||
summary: reasoning.summary_text,
|
||||
content: reasoning.raw_content,
|
||||
},
|
||||
CoreTurnItem::CommandExecution(command) => ThreadItem::CommandExecution {
|
||||
id: command.id,
|
||||
plugin_id: command.plugin_id,
|
||||
script_path: command.script_path,
|
||||
command: shlex_join(&command.command),
|
||||
cwd: command.cwd.clone().into(),
|
||||
process_id: command.process_id,
|
||||
source: command.source.into(),
|
||||
status: command.status.into(),
|
||||
command_actions: command_actions_for_path_uri(&command.parsed_cmd, &command.cwd),
|
||||
aggregated_output: command
|
||||
.aggregated_output
|
||||
.filter(|output| !output.is_empty()),
|
||||
exit_code: command.exit_code,
|
||||
duration_ms: command
|
||||
.duration
|
||||
.and_then(|duration| i64::try_from(duration.as_millis()).ok()),
|
||||
},
|
||||
CoreTurnItem::CommandExecution(command) => {
|
||||
let presentation = CommandExecutionPresentation::from_raw(
|
||||
&command.command,
|
||||
&command.parsed_cmd,
|
||||
&command.cwd,
|
||||
);
|
||||
ThreadItem::CommandExecution {
|
||||
id: command.id,
|
||||
plugin_id: command.plugin_id,
|
||||
script_path: command.script_path,
|
||||
command: presentation.command,
|
||||
cwd: command.cwd.clone().into(),
|
||||
process_id: command.process_id,
|
||||
source: command.source.into(),
|
||||
status: command.status.into(),
|
||||
command_actions: presentation.command_actions,
|
||||
aggregated_output: command
|
||||
.aggregated_output
|
||||
.filter(|output| !output.is_empty()),
|
||||
exit_code: command.exit_code,
|
||||
duration_ms: command
|
||||
.duration
|
||||
.and_then(|duration| i64::try_from(duration.as_millis()).ok()),
|
||||
}
|
||||
}
|
||||
CoreTurnItem::DynamicToolCall(call) => ThreadItem::DynamicToolCall {
|
||||
id: call.id,
|
||||
namespace: call.namespace,
|
||||
|
||||
@@ -2927,10 +2927,19 @@ fn core_turn_item_into_thread_item_converts_supported_variants() {
|
||||
plugin_id: Some("sample@openai-curated".to_string()),
|
||||
script_path: Some("scripts/run.py".to_string()),
|
||||
process_id: Some("pid-1".to_string()),
|
||||
command: vec!["echo".to_string(), "done".to_string()],
|
||||
command: vec![
|
||||
"git".to_string(),
|
||||
"-c".to_string(),
|
||||
"http.extraHeader=Authorization: Bearer example_synthetic_bearer_token_123456"
|
||||
.to_string(),
|
||||
"-c".to_string(),
|
||||
"http.extraHeader=X-Trace:example".to_string(),
|
||||
"push".to_string(),
|
||||
],
|
||||
cwd: PathUri::from_abs_path(&test_path_buf("/tmp").abs()),
|
||||
parsed_cmd: vec![codex_protocol::parse_command::ParsedCommand::Unknown {
|
||||
cmd: "echo done".to_string(),
|
||||
cmd: "git -c 'http.extraHeader=Authorization: Bearer example_synthetic_bearer_token_123456' -c http.extraHeader=X-Trace:example push"
|
||||
.to_string(),
|
||||
}],
|
||||
source: CoreExecCommandSource::Agent,
|
||||
interaction_input: None,
|
||||
@@ -2949,13 +2958,15 @@ fn core_turn_item_into_thread_item_converts_supported_variants() {
|
||||
id: "exec-1".to_string(),
|
||||
plugin_id: Some("sample@openai-curated".to_string()),
|
||||
script_path: Some("scripts/run.py".to_string()),
|
||||
command: "echo done".to_string(),
|
||||
command: "git -c 'http.extraHeader=Authorization: Bearer [REDACTED_SECRET]' -c 'http.extraHeader=X-Trace:example' push"
|
||||
.to_string(),
|
||||
cwd: LegacyAppPathString::from_abs_path(&test_path_buf("/tmp").abs()),
|
||||
process_id: Some("pid-1".to_string()),
|
||||
source: CommandExecutionSource::Agent,
|
||||
status: CommandExecutionStatus::Completed,
|
||||
command_actions: vec![CommandAction::Unknown {
|
||||
command: "echo done".to_string(),
|
||||
command: "git -c 'http.extraHeader=Authorization: Bearer [REDACTED_SECRET]' -c http.extraHeader=X-Trace:example push"
|
||||
.to_string(),
|
||||
}],
|
||||
aggregated_output: Some("done\n".to_string()),
|
||||
exit_code: Some(0),
|
||||
|
||||
Reference in new issue
Block a user