Files
codex/scripts/start-codex-exec.sh
starr-openai d626dc3895 Run exec-server fs operations through sandbox helper (#17294)
## Summary
- run exec-server filesystem RPCs requiring sandboxing through a
`codex-fs` arg0 helper over stdin/stdout
- keep direct local filesystem execution for `DangerFullAccess` and
external sandbox policies
- remove the standalone exec-server binary path in favor of top-level
arg0 dispatch/runtime paths
- add sandbox escape regression coverage for local and remote filesystem
paths

## Validation
- `just fmt`
- `git diff --check`
- remote devbox: `cd codex-rs && bazel test --bes_backend=
--bes_results_url= //codex-rs/exec-server:all` (6/6 passed)

---------

Co-authored-by: Codex <noreply@openai.com>
2026-04-12 18:36:03 -07:00

190 lines
4.9 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
usage() {
echo "Usage: $0 HOST [RSYNC_OPTION]..." >&2
}
if [[ $# -lt 1 ]]; then
usage
exit 2
fi
case "$1" in
-h|--help)
usage
exit 0
;;
esac
remote_host="$1"
shift
remote_path='~/code/codex-sync'
local_exec_server_port="${CODEX_REMOTE_EXEC_SERVER_LOCAL_PORT:-8765}"
remote_exec_server_start_timeout_seconds="${CODEX_REMOTE_EXEC_SERVER_START_TIMEOUT_SECONDS:-15}"
remote_exec_server_pid=''
remote_exec_server_log_path=''
remote_exec_server_pid_path=''
remote_repo_root=''
cleanup() {
local exit_code=$?
trap - EXIT INT TERM
if [[ -n "${remote_exec_server_pid_path}" ]]; then
ssh "${remote_host}" \
"if [[ -f '${remote_exec_server_pid_path}' ]]; then kill \$(cat '${remote_exec_server_pid_path}') >/dev/null 2>&1 || true; fi; rm -f '${remote_exec_server_pid_path}' '${remote_exec_server_log_path}'" \
>/dev/null 2>&1 || true
fi
exit "${exit_code}"
}
trap cleanup EXIT INT TERM
if ! command -v git >/dev/null 2>&1; then
echo "git is required" >&2
exit 1
fi
if ! command -v ssh >/dev/null 2>&1; then
echo "ssh is required" >&2
exit 1
fi
if ! command -v rsync >/dev/null 2>&1; then
echo "local rsync is required" >&2
exit 1
fi
repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || {
echo "run this script from inside a git repository" >&2
exit 1
}
ssh "${remote_host}" "mkdir -p ${remote_path}"
if ! ssh "${remote_host}" 'command -v rsync >/dev/null 2>&1'; then
echo "remote rsync is required on ${remote_host}" >&2
exit 1
fi
sync_instance_id="$(date +%s)-$$"
rsync \
--archive \
--compress \
--human-readable \
--itemize-changes \
--exclude '.git/' \
--exclude 'codex-rs/target/' \
--filter=':- .gitignore' \
"$@" \
"${repo_root}/" \
"${remote_host}:${remote_path}/" \
>&2
remote_exec_server_log_path="/tmp/codex-exec-server-${sync_instance_id}.log"
remote_exec_server_pid_path="/tmp/codex-exec-server-${sync_instance_id}.pid"
remote_start_output="$(
ssh "${remote_host}" bash -s -- \
"${remote_exec_server_log_path}" \
"${remote_exec_server_pid_path}" \
"${remote_exec_server_start_timeout_seconds}" <<'EOF'
set -euo pipefail
remote_exec_server_log_path="$1"
remote_exec_server_pid_path="$2"
remote_exec_server_start_timeout_seconds="$3"
remote_repo_root="$HOME/code/codex-sync"
remote_codex_rs="$remote_repo_root/codex-rs"
cd "${remote_codex_rs}"
cargo build -p codex-cli --bin codex
rm -f "${remote_exec_server_log_path}" "${remote_exec_server_pid_path}"
nohup ./target/debug/codex exec-server --listen ws://127.0.0.1:0 \
>"${remote_exec_server_log_path}" 2>&1 &
remote_exec_server_pid="$!"
echo "${remote_exec_server_pid}" >"${remote_exec_server_pid_path}"
deadline=$((SECONDS + remote_exec_server_start_timeout_seconds))
while (( SECONDS < deadline )); do
if [[ -s "${remote_exec_server_log_path}" ]]; then
listen_url="$(head -n 1 "${remote_exec_server_log_path}" || true)"
if [[ "${listen_url}" == ws://* ]]; then
printf 'remote_exec_server_pid=%s\n' "${remote_exec_server_pid}"
printf 'remote_exec_server_log_path=%s\n' "${remote_exec_server_log_path}"
printf 'remote_repo_root=%s\n' "${remote_repo_root}"
printf 'listen_url=%s\n' "${listen_url}"
exit 0
fi
fi
if ! kill -0 "${remote_exec_server_pid}" >/dev/null 2>&1; then
cat "${remote_exec_server_log_path}" >&2 || true
echo "remote exec server exited before reporting a listen URL" >&2
exit 1
fi
sleep 0.1
done
cat "${remote_exec_server_log_path}" >&2 || true
echo "timed out waiting for remote exec server listen URL" >&2
exit 1
EOF
)"
listen_url=''
while IFS='=' read -r key value; do
case "${key}" in
remote_exec_server_pid)
remote_exec_server_pid="${value}"
;;
remote_exec_server_log_path)
remote_exec_server_log_path="${value}"
;;
remote_repo_root)
remote_repo_root="${value}"
;;
listen_url)
listen_url="${value}"
;;
esac
done <<< "${remote_start_output}"
if [[ -z "${remote_exec_server_pid}" || -z "${listen_url}" || -z "${remote_repo_root}" ]]; then
echo "failed to parse remote exec server startup output" >&2
exit 1
fi
remote_exec_server_port="${listen_url##*:}"
if [[ -z "${remote_exec_server_port}" || "${remote_exec_server_port}" == "${listen_url}" ]]; then
echo "failed to parse remote exec server port from ${listen_url}" >&2
exit 1
fi
echo "Remote exec server: ${listen_url}"
echo "Remote exec server log: ${remote_exec_server_log_path}"
echo "Press Ctrl-C to stop the SSH tunnel and remote exec server."
echo "Start codex via: "
printf ' CODEX_EXEC_SERVER_URL=ws://127.0.0.1:%s codex -C %q\n' \
"${local_exec_server_port}" \
"${remote_repo_root}"
ssh \
-nNT \
-o ControlMaster=no \
-o ControlPath=none \
-o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-L "${local_exec_server_port}:127.0.0.1:${remote_exec_server_port}" \
"${remote_host}"