claude-native pre-seeds workspace trust globally, allowing unreviewed project hooks to execute at startup
Summary
claude-native pre-seeds Claude Code's workspace trust globally and pre-launch, without user confirmation. As a consequence, a project-controlled .claude/settings.json SessionStart hook executes as the runner user during startup — before the user has personally seen or accepted Claude's warning that the workspace "can read, edit, and execute files".
Found while auditing whether the kimi-native trust defect (#6424) had parity in the Claude and Codex harnesses. It does not — Claude's handling is structurally safer in every other respect (no startup race, no swallowed failures, no symlink escape) — but this one grant is real and, unlike the kimi case, it mutates global user state.
Verified reproduction
Against installed Claude Code 2.1.259, in isolated /tmp homes:
- Seed only the two fields omnigent seeds —
hasCompletedOnboardingandhasTrustDialogAccepted. - Supply an otherwise empty invocation
--settingsfile (as omnigent does). - Place a project
.claude/settings.jsonSessionStarthook that creates a marker file.
Result: the marker was created — project_hook_started=yes. The hook ran with no trust prompt.
Why this is omnigent's to fix, not Claude's
ensure_claude_workspace_trustedwrites trust into the runner user's real~/.claude.json(omnigent/claude_native_bridge.py:1149,:1188), called pre-launch fromomnigent/runner/native/orchestration.py:6624. Unlike kimi-native, there is no isolated session home — the terminal env does not overrideHOMEorCLAUDE_CONFIG_DIR(orchestration.py:7150), so the grant is global and persistent, not session-scoped.- omnigent adds its own invocation settings but does not disable project settings (
claude_native_bridge.py:1895,:1899), so project-defined hooks remain live.
Scope — what is not affected
- Project MCP servers are still separately gated. With trust seeded and omnigent-style
--mcp-config/--settings, Claude2.1.259still displayed a "New MCP server found" consent menu and did not start the project server. The first-message path treats that menu as an overlay and sendsEscape, which safely declines. So this is not the same as the kimi project-MCP grant discussed on #6424. - The seed writes only
hasCompletedOnboarding/hasTrustDialogAccepted(claude_native_bridge.py:1122,:1160,:1175). It does not write project-MCP approval.
Impact
Opening a newly cloned, third-party, or otherwise unreviewed workspace through claude-native can execute project-defined hook commands at startup. Reviewing an attacker-authored branch is enough. The trust gate that exists to prevent this is auto-defeated, and because the write lands in the real ~/.claude.json the grant outlives the session.
Suggested directions (not a prescription)
- Disable project settings for runner-owned sessions (invocation settings only), so project hooks require an explicit opt-in.
- Or scope the trust seed to an isolated Claude home instead of the user's global
~/.claude.json, as kimi-native now does. - Or prompt once per workspace before seeding.
Notes
- Verified against installed Claude Code
2.1.259only, not every release. - Base for all code citations:
upstream/main@2e931d11e. - Independent of the kimi symlink-escape hazard and of project-MCP consent.
Source: omnigent-ai/omnigent