fix(agent): keep strict permissions server-side, not in repo
The previous commit put .claude/settings.json IN THE REPO, which would
have applied its strict deny rules to ANY Claude Code invocation from
this cwd — including the human user's interactive dev sessions on their
own machine. That's wrong; the production agent's lockdown should not
constrain the developer.
Remove the committed file and gitignore .claude/ entirely. The repo is
permission-neutral now.
Strict permissions for the production agent come from two server-only
sources:
1. CLI flags in agent/claude_wrapper.py (--allowed-tools +
--disallowed-tools, passed by the systemd-spawned subprocess only)
2. /var/lib/overlord-agent/.claude/settings.json (the agent's own HOME
— separate from any user's .claude/)
Also bumps claude_wrapper.py with the explicit --disallowed-tools list
of meta-tools (ToolSearch, Monitor, TodoWrite, TaskOutput, Skill, cron
tools, etc.) that the --allowed-tools whitelist does not block on its
own. Verified empirically: with only --allowed-tools, ToolSearch was
still callable; --disallowed-tools is required.
This commit is contained in:
parent
f894399165
commit
e780f249d1
3 changed files with 54 additions and 23 deletions
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"WebFetch(domain:acpedia.org)"
|
||||
],
|
||||
"deny": [
|
||||
"Bash",
|
||||
"Write",
|
||||
"Edit",
|
||||
"Read",
|
||||
"Glob",
|
||||
"Grep",
|
||||
"NotebookEdit",
|
||||
"WebSearch"
|
||||
],
|
||||
"ask": []
|
||||
},
|
||||
"enableAllProjectMcpServers": true
|
||||
}
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
|
|
@ -3,7 +3,9 @@ __pycache__
|
|||
static/v2/
|
||||
frontend/node_modules/
|
||||
|
||||
# Claude Code per-machine permissions (do NOT deploy to server — production
|
||||
# agent must run with the strict permissions in committed .claude/settings.json)
|
||||
.claude/settings.local.json
|
||||
.claude/settings.local.json.*
|
||||
# Claude Code config — never commit. The production agent's strict
|
||||
# permissions live server-side at /var/lib/overlord-agent/.claude/
|
||||
# (and via CLI flags in agent/claude_wrapper.py). The repo stays
|
||||
# permission-neutral so devs can `claude` interactively here without
|
||||
# inheriting production-agent restrictions.
|
||||
.claude/
|
||||
|
|
|
|||
|
|
@ -91,6 +91,50 @@ async def ask_claude(message: str, session_id: str) -> ClaudeResult:
|
|||
]
|
||||
)
|
||||
|
||||
# CRITICAL: Claude Code's built-in meta-tools (ToolSearch, Monitor, etc.)
|
||||
# bypass the --allowed-tools whitelist. They come from Anthropic's tool
|
||||
# registry rather than from local MCP servers. We must explicitly DISALLOW
|
||||
# them — confirmed by testing that ToolSearch was reachable even with
|
||||
# `--permission-mode dontAsk` and a tight --allowed-tools list.
|
||||
disallowed_tools = ",".join(
|
||||
[
|
||||
# File / shell / search built-ins (defense in depth — already not
|
||||
# in allow list, but if someone toggles permission-mode this
|
||||
# belt-and-suspenders the deny side).
|
||||
"Bash",
|
||||
"Write",
|
||||
"Edit",
|
||||
"Read",
|
||||
"Glob",
|
||||
"Grep",
|
||||
"NotebookEdit",
|
||||
# Network built-ins
|
||||
"WebSearch",
|
||||
# Tool / session meta-tools — these can list, load, or chain
|
||||
# into other tools and must NOT be reachable.
|
||||
"ToolSearch",
|
||||
"Monitor",
|
||||
"TaskOutput",
|
||||
"TaskStop",
|
||||
"TodoWrite",
|
||||
"Skill",
|
||||
"EnterPlanMode",
|
||||
"ExitPlanMode",
|
||||
"EnterWorktree",
|
||||
"ExitWorktree",
|
||||
"AskUserQuestion",
|
||||
"ListMcpResourcesTool",
|
||||
"ReadMcpResourceTool",
|
||||
"PushNotification",
|
||||
# Scheduling / cron — the agent must never schedule itself.
|
||||
"CronCreate",
|
||||
"CronList",
|
||||
"CronDelete",
|
||||
"ScheduleWakeup",
|
||||
"RemoteTrigger",
|
||||
]
|
||||
)
|
||||
|
||||
# Pick --session-id (creates) vs --resume (continues) based on whether
|
||||
# the session JSONL already exists on disk.
|
||||
is_new = not _session_exists(session_id)
|
||||
|
|
@ -105,6 +149,10 @@ async def ask_claude(message: str, session_id: str) -> ClaudeResult:
|
|||
"json",
|
||||
"--allowed-tools",
|
||||
allowed_tools,
|
||||
# Built-in meta-tools that --allowed-tools does NOT block — must
|
||||
# be explicitly listed here.
|
||||
"--disallowed-tools",
|
||||
disallowed_tools,
|
||||
# CRITICAL: dontAsk auto-DENIES anything outside --allowed-tools.
|
||||
# Do NOT use bypassPermissions here — that mode ignores the whitelist
|
||||
# entirely and lets the model call Bash/Write/Edit/etc. (verified
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue