mirror of
https://github.com/openai/codex.git
synced 2026-04-25 15:15:15 +00:00
## 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>
190 lines
4.9 KiB
Bash
Executable File
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}"
|