Files
orca/docs/reference/restored-shell-codex-hook-trust-validation.md
T

4.5 KiB

Restored-shell Codex hook-trust validation

Root cause

Restored daemon shells became interactive after the daemon and hook server started, while managed Codex hook reconciliation remained an unawaited background task. A retained shell could therefore launch manually typed codex against its launch-time managed home before Orca refreshed that home's hook definitions and trusted hashes. The background repair then made persisted state and later hooks/list checks look healthy.

The retained shell's launch-time home is independent of the currently selected Codex routing lane. Startup now inventories authoritative live daemon PTYs on every retained-shell startup, resolves only registered Orca-managed host homes, and reconciles those homes before the startup gate completes.

Security boundary

  • Shared and legacy managed homes resolve only to Orca's private runtime home.
  • Per-account homes pass existing Orca ownership validation.
  • Real-home, WSL, SSH/non-host, unknown, missing-account, and unowned paths are skipped.
  • Enabled settings reinstall/repair only Orca-managed hooks.
  • Disabled settings remove only Orca-managed entries while preserving user hooks.

Electron/CDP reproduction

Build:

pnpm run build:electron-vite

Isolated launch (the shortened profile path avoids the Unix-socket path limit):

/usr/bin/env -u ELECTRON_RUN_AS_NODE -u CODEX_HOME -u ORCA_CODEX_HOME \
  PATH='/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin' \
  HOME='/tmp/orca-rce-060679/home' \
  USERPROFILE='/tmp/orca-rce-060679/home' \
  ORCA_E2E_USER_DATA_DIR='/tmp/orca-rce-060679' \
  ORCA_E2E_HOME_DIR='/tmp/orca-rce-060679/home' \
  ORCA_E2E_HEADFUL=1 NODE_ENV=development \
  '<worktree>/node_modules/.pnpm/electron@43.1.0/node_modules/electron/dist/Electron.app/Contents/MacOS/Electron' \
  out/main/index.js --remote-debugging-port=9460

Validation used agent-browser --cdp 9460 only. A real floating-shell PTY was created, the Electron main process was terminated without stopping the daemon, its pane registry retained the managed shared-home route, and an Orca lifecycle-hook trusted_hash was made stale. A deterministic Codex fixture was added only after startup so it reported the same review/ready state from the managed config without allowing generic startup CLI detection to hide the race.

Local capture filenames (uploaded to the PR as GitHub attachments; intentionally not committed):

  • Before: restored-codex-hook-review-before.png
  • After: restored-codex-hook-trusted-after.png
  • Fresh pane: fresh-codex-hook-trusted.png
  • Disabled hooks after retained restart: restored-codex-hooks-disabled.png

The pre-fix restart retained the stale hash and showed Hooks need review. The fixed restart repaired it before awaitFirstWindowStartupServices() resolved and the same retained PTY showed trusted/ready. A fresh pane reached normal Codex onboarding without a hook-review prompt. With agentStatusHooksEnabled: false, a retained restart left hooks.json as { "hooks": {} } and config.toml with an empty [hooks.state].

Automated validation

pnpm exec vitest run \
  src/main/codex/retained-codex-hook-state.test.ts \
  src/main/startup/desktop-startup-ordering.test.ts \
  src/main/codex-accounts/runtime-home-service.test.ts

pnpm run typecheck:node

pnpm exec oxfmt --check \
  src/main/index.ts \
  src/main/codex-accounts/runtime-home-service.ts \
  src/main/codex-accounts/runtime-home-service.test.ts \
  src/main/codex/retained-codex-hook-state.ts \
  src/main/codex/retained-codex-hook-state.test.ts \
  src/main/startup/desktop-startup-ordering.test.ts

pnpm exec oxlint \
  src/main/index.ts \
  src/main/codex-accounts/runtime-home-service.ts \
  src/main/codex-accounts/runtime-home-service.test.ts \
  src/main/codex/retained-codex-hook-state.ts \
  src/main/codex/retained-codex-hook-state.test.ts \
  src/main/startup/desktop-startup-ordering.test.ts

git diff --check

Results: 113 focused tests passed; node typecheck, formatting, direct oxlint, diff check, and Electron build passed. The aggregate changed-code script was not used because Node 26's unsupported-engine warning breaks its JSON parser; direct oxlint covered all changed source files.

Remaining risk

The repair deliberately covers only host-side Orca-managed runtime homes recorded for live PTYs. Folder workspaces use the same verified host-home path; real-home, WSL, SSH, and arbitrary user or repository hook paths are not auto-trusted, and their existing launch-specific flows remain unchanged.