feat: exec policy integration in shell mcp (#7609)

adding execpolicy support into the `posix` mcp

Co-authored-by: Michael Bolin <mbolin@openai.com>
This commit is contained in:
zhao-oai
2025-12-04 21:55:54 -08:00
committed by GitHub
parent 4c9762d15c
commit b1c918d8f7
6 changed files with 171 additions and 41 deletions

View File

@@ -1,5 +1,6 @@
use std::path::Path;
use codex_execpolicy::Policy;
use rmcp::ErrorData as McpError;
use rmcp::RoleServer;
use rmcp::model::CreateElicitationRequestParam;
@@ -11,15 +12,10 @@ use rmcp::service::RequestContext;
use crate::posix::escalate_protocol::EscalateAction;
use crate::posix::escalation_policy::EscalationPolicy;
use crate::posix::stopwatch::Stopwatch;
use std::sync::Arc;
use tokio::sync::RwLock;
/// This is the policy which decides how to handle an exec() call.
///
/// `file` is the absolute, canonical path to the executable to run, i.e. the first arg to exec.
/// `argv` is the argv, including the program name (`argv[0]`).
/// `workdir` is the absolute, canonical path to the working directory in which to execute the
/// command.
pub(crate) type ExecPolicy = fn(file: &Path, argv: &[String], workdir: &Path) -> ExecPolicyOutcome;
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum ExecPolicyOutcome {
Allow {
run_with_escalated_permissions: bool,
@@ -33,21 +29,25 @@ pub(crate) enum ExecPolicyOutcome {
/// ExecPolicy with access to the MCP RequestContext so that it can leverage
/// elicitations.
pub(crate) struct McpEscalationPolicy {
policy: ExecPolicy,
/// In-memory execpolicy rules that drive how to handle an exec() call.
policy: Arc<RwLock<Policy>>,
context: RequestContext<RoleServer>,
stopwatch: Stopwatch,
preserve_program_paths: bool,
}
impl McpEscalationPolicy {
pub(crate) fn new(
policy: ExecPolicy,
policy: Arc<RwLock<Policy>>,
context: RequestContext<RoleServer>,
stopwatch: Stopwatch,
preserve_program_paths: bool,
) -> Self {
Self {
policy,
context,
stopwatch,
preserve_program_paths,
}
}
@@ -103,7 +103,9 @@ impl EscalationPolicy for McpEscalationPolicy {
argv: &[String],
workdir: &Path,
) -> Result<EscalateAction, rmcp::ErrorData> {
let outcome = (self.policy)(file, argv, workdir);
let policy = self.policy.read().await;
let outcome =
crate::posix::evaluate_exec_policy(&policy, file, argv, self.preserve_program_paths)?;
let action = match outcome {
ExecPolicyOutcome::Allow {
run_with_escalated_permissions,