Skip to content

Which file mode should the daemon leave on a user's own config file? #156

Open

Description

@LutzLange

Summary

The daemon writes into files it owns completely (managed settings, the Codex/Grok/OpenCode configs with its header, the Claude Desktop helper script) and into files that belong to the user (Claude Code ~/.claude/settings.json in --user mode, VS Code settings.json, chatLanguageModels.json, Copilot CLI providers.json). For the second group the mode handling grew per feature, and it is not consistent today. I'd like to agree on the intended behaviour before changing anything.

Behaviour on main (ff46fc4, Unix)

File Written with On identical bytes at a looser mode Removal of our entries
Daemon-owned files (managed settings, Codex/Grok/OpenCode configs, helper script 0755) the daemon's mode (0644/0755) rewritten at that mode (#146) n/a
Claude Code user settings.json (merge) always 0644 rewritten at 0644 (#146) keeps the mode it finds
VS Code settings.json, chatLanguageModels.json, Copilot CLI providers.json (carry the pairing value) 0600 rewritten at 0600 keeps the mode it finds

Two consequences for the Claude Code user file:

Every write goes through the umask (secure_fs::atomic_write creates the temporary file with the planned mode), so removal "keeps the mode it finds" as far as the umask allows: a 0664 file comes back as 0644 under umask 022. That should stay: the umask is the user's ceiling, and the daemon should not write past it. On Windows the mode argument is ignored and the file gets its folder's ACL.

What the daemon writes into the user files

Nothing confidential goes into the Claude Code user settings (the apiKeyHelper command name, the gateway URL, hooks, announcements; the credential is fetched at run time). The pairing value is a secret: the files that carry it need 0600, since the proxy on 127.0.0.1 is reachable by every local account. The daemon-owned files hold commands that tools execute (hooks, apiKeyHelper, the helper script, MCP commands), so write access by others is the concern there, not read access.

Proposal

Split by who owns the file:

  1. Daemon-owned files: unchanged (the daemon's mode, drift repaired).
  2. User files carrying the pairing value: unchanged (0600, a looser file tightened).
  3. User files without a secret (today only the Claude Code user settings merge): a rewrite keeps the file's mode, through the umask like every write; a file the merge creates gets 0644 through the umask. No tightening of an unchanged file.

An alternative is "never widen": owner read/write, group and other bits at most what both the file and the planned mode allow (0600 stays 0600, 0664 becomes 0644). It is stricter than (3) but still changes a mode the user chose.

Questions

  • Is "keep the user's mode" (3) the behaviour we want for user files without a secret, or "never widen", or the current 0644?
  • Windows: is the folder ACL enough for the user files, or should a rewrite keep a file's own ACL (ReplaceFileW)?

Happy to send the change once we agree on the rule.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions