Found an issue with the latest update about IDE extension: IPC socket dir /tmp/codex-ipc is not user-namespaced — EACCES on shared multi-user hosts (HPC login nodes)

Open 💬 2 comments Opened Jun 11, 2026 by RU0804
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

The thing is that I cannot open my codex extension on my Cursor while connected with our university's cluster.

On a shared multi-user Linux host (university HPC login node, RHEL 9), the Codex IDE extension fails to start: the panel never connects, and the extension log spams once per second:

[error] [IpcRouterManager] Server error errorCode=EACCES
errorMessage="listen EACCES: permission denied /tmp/codex-ipc/ipc-<pid>.sock"
at cg.startRouterIfNeeded (.../openai.chatgpt-26.602.71036-linux-x64/out/extension.js)
at async pl.connect (...)

I then checked with Claude code, here is the summary:

Root cause

IpcRouterManager binds its socket under a fixed shared path os.tmpdir()/codex-ipc/ (extension.js: path.join(os.tmpdir(), "codex-ipc"), created with default 0755 perms). On a multi-user machine, whichever user runs Codex first owns /tmp/codex-ipc; every other user then gets EACCES forever and the extension is unusable for them. On our cluster the directory was created by another user weeks ago, so the extension is permanently broken for everyone else on that node.

This regressed in the extension update 26.601.20914 → 26.602.71036 (codex-cli 0.137.0-alpha.4): 26.601 had no IpcRouterManager and worked fine in the same environment (VS Code/Cursor Remote-SSH into the cluster).

Expected behavior

The IPC directory should be per-user, e.g. $XDG_RUNTIME_DIR/codex-ipc, os.tmpdir()/codex-ipc-$UID with 0700 perms, or under $CODEX_HOME. Also, a fatal bind failure should surface as a user-visible error instead of a silent 1/s retry loop.

Workaround

Setting TMPDIR to a per-user directory (e.g. /tmp/$USER) before the remote server starts fixes it, since the path is derived from os.tmpdir().

Environment

  • Extension: openai.chatgpt 26.602.71036 (codex-cli 0.137.0-alpha.4)
  • Host: shared HPC login node, RHEL 9.x, x86_64, accessed via Cursor Remote-SSH
  • Worked on: same setup with extension 26.601.20914

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #26761
  • #26485

Powered by Codex Action

wgu9 · 2 months ago

I checked the open-source side for the matching IPC path. One detail worth calling out: the current TUI client already namespaces the socket filename by UID, but it still uses a shared parent directory.

Relevant code:

  • codex-rs/tui/src/ide_context/ipc.rs
  • default_ipc_socket_path() on Unix returns:
std::env::temp_dir()
    .join("codex-ipc")
    .join(format!("ipc-{uid}.sock"))

So the Rust/TUI side avoids direct filename collision with ipc-$uid.sock, but the parent remains os.tmpdir()/codex-ipc / /tmp/codex-ipc. On a shared host, if that parent directory was created by another user with ordinary 0755 permissions, other users still cannot create their own per-UID socket inside it. That matches the reported EACCES even if socket names are unique.

The fix should therefore user-namespace the directory, not only the socket filename. Safer options would be something like:

  • $XDG_RUNTIME_DIR/codex-ipc/ when available;
  • otherwise /tmp/codex-ipc-$UID/ with 0700 permissions;
  • or another per-user runtime dir under Codex home if appropriate for Remote-SSH.

It would also be useful for both sides of the IPC contract to use the same path resolver so the extension/server and CLI/TUI cannot drift.

Suggested regression coverage:

  1. Unit-test the Unix resolver to ensure it never returns a socket path under a shared non-user-namespaced parent like /tmp/codex-ipc/ipc-*.
  2. Test the fallback when XDG_RUNTIME_DIR is unset.
  3. If the extension has a parallel JS resolver, add the same test there so the extension and Rust client agree.
  4. Surface a user-visible startup error when binding the IPC socket fails with EACCES, rather than retrying silently once per second.

This is high impact for shared Linux/Remote-SSH/HPC environments because one stale directory owned by another user can make the extension unusable for every later user on the node.