[Bug] /tmp/claude-settings-<hash>.json shared across Linux users — second user crashes with EACCES (exit code 1)

Resolved 💬 3 comments Opened Apr 26, 2026 by TimChesko Closed Apr 26, 2026

Summary

When two or more Linux users on the same machine use Claude Code (Cowork / remote SSH agent), the second user's session crashes immediately with Claude Code process exited with code 1 because CCD writes its temporary settings file to /tmp/claude-settings-<hash>.json where the <hash> is not unique per-user. The first user to start a session creates the file owned by them; every subsequent user hits EACCES trying to overwrite it, even though the file is 0666.

Environment

  • Claude Desktop: 1.4758 (Windows host)
  • Remote agent CLI: ccd-cli 2.1.119
  • Server OS: Ubuntu 24.04, kernel default fs.protected_regular = 2
  • Two Linux users on the same VPS (tolya uid 1001, tim uid 1002), independent SSH keys, both connecting via Claude Desktop's remote-agent feature

Reproduction

  1. User A SSHs into the server via Claude Desktop's remote agent. Session starts fine; CCD creates /tmp/claude-settings-44136fa355b3678a.json (mode 664, owner=A).
  2. User B SSHs into the same server via Claude Desktop's remote agent.
  3. CCD spawns ccd-cli for user B. ccd-cli tries to open the same path with O_WRONLY|O_CREAT|O_TRUNC, 0666.
  4. Kernel returns EACCES because of fs.protected_regular: in a sticky-bit directory, you cannot O_CREAT an existing regular file you don't own (anti symlink/hardlink-attack hardening, on by default since kernel 4.19).

Actual behaviour

ccd-cli exits with code 1 within ~300-400 ms. Stderr (visible in ~/.claude/logs/ssh.log):

[RemoteProcess:...] stderr: Error processing settings: EACCES: permission denied, open '/tmp/claude-settings-44136fa355b3678a.json'
[RemoteProcess:...] Exited, code=1, duration=314ms

The hash 44136fa355b3678a is identical for every user on the host.

$ ls -la /tmp/claude-settings-*
-rw-rw-r-- 1 userA userA 2 Apr 26 06:15 /tmp/claude-settings-44136fa355b3678a.json

$ sudo -u userB strace -e openat -f -- bash -c 'echo {} > /tmp/claude-settings-44136fa355b3678a.json'
openat(AT_FDCWD, "/tmp/claude-settings-44136fa355b3678a.json", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 EACCES (Permission denied)

chmod 666 does not fix it — the kernel block is on O_CREAT of an existing regular file you don't own in a sticky directory, regardless of mode.

Expected behaviour

The settings file path should include something user-unique (UID, $USER, or $HOME in the hash input), so each Linux user gets their own file.

Workaround

Delete the file as root before the second user starts a session:

sudo rm /tmp/claude-settings-*.json

This works once but breaks the original user's next session, because now they hit the same EACCES.

Suggested fix

Use any of these instead of /tmp/claude-settings-<hash>.json:

  • $XDG_RUNTIME_DIR/claude-settings-<hash>.json — systemd already creates /run/user/<uid> with mode 700 per user
  • $HOME/.cache/claude/settings-<hash>.json
  • Include UID / $USER in the hash input so the path becomes per-user even in /tmp

Notes

  • Same bug presumably affects any other multi-user Linux dev box (shared dev servers are a common Claude Code remote-agent setup).
  • Doesn't reproduce on single-user installs (macOS/Windows) because there's only one user touching the file.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗