Skip to content

fix(policy): move .claude.lock to allow_file for least-privilege access - #733

Merged
lukehinds merged 3 commits into
nolabs-ai:mainfrom
kipz:kipz/fix-claude-lock-allow
Apr 22, 2026
Merged

fix(policy): move .claude.lock to allow_file for least-privilege access#733
lukehinds merged 3 commits into
nolabs-ai:mainfrom
kipz:kipz/fix-claude-lock-allow

Conversation

@kipz

@kipz kipz commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Use file-level allow instead of directory-level allow for .claude.lock.

Use file-level allow instead of directory-level allow for .claude.lock.

Signed-off-by: Christine Le <christine.le@datadoghq.com>
@github-actions github-actions Bot added the bug Something isn't working label Apr 22, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the policy configuration by moving the $HOME/.claude.lock entry from the directory-based allow list to the allow_file list. While this change correctly applies least-privilege principles for a single file, feedback indicates it will cause a failure in the test_embedded_claude_code_profile_uses_platform_groups_for_os_paths unit test, which must be updated to reflect the new configuration.

Comment thread crates/nono-cli/data/policy.json
kipz added 2 commits April 22, 2026 14:13
The preceding commit moved .claude.lock to allow_file for the claude-code
profile but left existing tests asserting against .filesystem.allow, and
the claude-no-kc profile still had .claude.lock under the directory-level
allow list. Update the tests to assert against allow_file and move
.claude.lock in claude-no-kc for consistency.

Signed-off-by: James Carnegie <me@kipz.org>
Addresses a security advisory flagged by cargo-audit.

Signed-off-by: James Carnegie <me@kipz.org>
@lukehinds
lukehinds merged commit e340be9 into nolabs-ai:main Apr 22, 2026
21 of 22 checks passed
@nf-matt

nf-matt commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Hi... I was able to solve my Claude Code (CLI) lock problems without any code change in nono. On macOS I was running into problems with files that needed to be recreated, because Seatbelt doesn't play nice with that. And I don't want CC to have direct access to $HOME.

I can't find anything that supports the idea that Claude needs to write a .claude.lock file to $HOME. 🫤

@lukehinds @kipz

export CLAUDE_CONFIG_DIR=${HOME}/.local/claude
nono ... --allow "${CLAUDE_CONFIG_DIR}" --allow "${XDG_STATE_HOME:-${HOME}/.local/state}/claude"

This was after a session asking Claude which directories/files I need to allow to sandbox it externally:

Claude Response

There are actually two different lock-related paths in Claude Code, and it matters which one you're asking about for sandboxing purposes.

1. The installer/auto-update lock — ~/.local/state/claude/locks/

This is a directory containing individual .lock files, one per version.

  • Full path: ~/.local/state/claude/locks/<version>.lock (e.g. 2.0.71.lock)
  • It's a regular file that stores the PID of the process holding the lock
  • It gets created by the installer when Claude Code is being installed or updated — the mechanism is a classic PID-based lock to prevent concurrent installations
  • It's also touched at runtime — there are reports of ENOENT: no such file or directory, stat '~/.local/state/claude/locks/2.0.35.lock' errors when the file is missing, which suggests the running CLI also stats the lockfile for its current version
  • Respects XDG_STATE_HOME if set (the ~/.local/state part is the XDG default)

For sandboxing: the ~/.local/state/claude/ directory (or $XDG_STATE_HOME/claude/) needs to be read/write and persistable across runs. If you make it ephemeral or read-only, you'll hit "Lock file is already being held" or ENOENT errors. Don't just allow locks/ — allow the whole ~/.local/state/claude/ tree, since other state lives there too.

2. The ~/.claude/ directory (session/runtime state)

This is a different thing — the main config+state dir. It contains shell-snapshots/ which holds runtime files removed when the session exits cleanly, plus other small cache and lock files that appear depending on which features you use and are safe to delete. If you set CLAUDE_CONFIG_DIR, every ~/.claude path lives under that directory instead.

So this is a directory, created on first run, containing a mix of config you author (CLAUDE.md, settings.json, skills/, etc.) and runtime state Claude writes (transcripts, snapshots, caches, ad-hoc lock files for features like MCP).

For sandboxing: this needs read/write too, and it's the one you can relocate via CLAUDE_CONFIG_DIR if you want all state in one sandbox-friendly location.

Practical sandbox recipe

At minimum, allow read/write to:

  • $CLAUDE_CONFIG_DIR (or ~/.claude/) — config, session state, snapshots, per-feature locks
  • $XDG_STATE_HOME/claude/ (or ~/.local/state/claude/) — installer/update lockfiles and version state
  • Plus the working directory and /tmp (or /tmp/claude-<uid>/), as usual

Setting CLAUDE_CONFIG_DIR and XDG_STATE_HOME to paths inside your sandbox is the cleanest approach — it consolidates everything Claude Code writes into locations you control, instead of trying to chase down files scattered across the home directory.

@lukehinds

Copy link
Copy Markdown
Contributor

@nf-matt is this something we should look at codifying into nono?

@nf-matt

nf-matt commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

@nf-matt is this something we should look at codifying into nono?

@lukehinds

That's a good question. One of my autonomy blockers was Claude Code CLI auth within nono. I've tuned in to all the PRs surrounding ~/.claude, its locks, etc. Nothing seemed to work until I set up a CLAUDE_CONFIG_DIR env var, and told nono to allow r/w access to it. CC seems to be fully working without any direct read or write access to $HOME.

It makes me wonder if most of those PRs were of little to no effect, or are maybe obsolete. I did see that some of what Claude Code writes has changed over time, so it's possible we no longer need some of the CC-specific code that's been merged. This could be a possible code simplification opportunity within nono.

It's a shame Anthropic doesn't fully adopt the XDG mindset, because they do use it for XDG_STATE_HOME for binary updates. The default should not be to help clutter $HOME.

To directly answer your question, I think a setup guide would help (and I can draft one if you like). And we could potentially add a runtime message if someone uses the claude-code profile but doesn't have CLAUDE_CONFIG_DIR set up.

I'll play with a branch locally, removing most of the PRs, and see if I'm still able to work with CC.

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants