mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-29 17:22:25 +01:00
fix(security): stop the agent from re-enabling tools an admin disabled (#6357)
* fix(security): stop the agent from re-enabling tools an admin disabled settings.json:disabled_tools is the only global tool-permission boundary the Settings > Agent Tools panel offers, yet manage_settings exposed an `enable_tool` action that removed entries from it. Any agent turn could undo the admin's restriction, and because the agent reads untrusted web pages, emails and documents, a planted instruction could re-enable bash, email or any other tool that had been switched off. The denylist can now only be narrowed from a turn: `disable_tool` and `list_tools` keep working, `enable_tool` is refused with a message that points the user to Settings > Agent Tools, and the action is dropped from the function schema, the prompt rule and the tool index so models are not steered into calling it. The free-form set/delete/reset actions were already unable to reach `disabled_tools`; a test now pins that. Fixes #5523 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UAB5sz5srMKR7rbeDFtdMH * fix(settings): close internal API tool-policy bypass Refuse global tool-policy replacement from internal-token requests even when an admin owner is impersonated, and block the same write in app_api. Route explicit image re-enable requests to list_tools with a Settings pointer. Keep disabled_tools outside general settings actions even if a default is added later. Remove the retired action from capability metadata. Validation: 573 focused tests passed; the running app rejected handler, generic API and encoded-path internal HTTP attempts while preserving human administrator controls. * fix(mcp): block agent writes to per-server MCP tool policy PATCH /api/mcp/servers/{id}/tools only checked require_admin, which accepts the internal tool token, and app_api still forwarded it, so an agent turn could re-enable MCP tools an admin had switched off. Refuse the internal token on that route (same check as POST /api/tools) and add PATCH /api/mcp/servers to the app_api blocklist, with regression tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BCbhLNC7mJsunxqfwwshqn --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Afonso Junior <chatgpt@yack.com.br>
This commit is contained in:
co-authored by
Claude Opus 5.5
Afonso Junior
parent
a646b59110
commit
57a1859f08
@@ -769,6 +769,8 @@ _APP_API_BLOCKLIST_PREFIXES = (
|
||||
# {"tasks": []} to /api/cookbook/state, which overwrote the whole file.
|
||||
# Use dedicated tools or UI flows instead.
|
||||
_APP_API_BLOCKLIST_METHOD_PATH = (
|
||||
("POST", "/api/tools"), # global tool policy is changed by a human in Settings
|
||||
("PATCH", "/api/mcp/servers"), # per-server MCP tool policy and server toggles, same reason
|
||||
("GET", "/api/email/accounts"), # owner-filtered in tool context; use list_email_accounts MCP tool
|
||||
("POST", "/api/cookbook/state"), # whole-file overwrite — agent must use serve_preset/serve_model instead
|
||||
("DELETE", "/api/cookbook/state"),
|
||||
@@ -893,6 +895,10 @@ async def do_app_api(content: str, owner: Optional[str] = None) -> Dict:
|
||||
if method not in ("GET", "POST", "PUT", "PATCH", "DELETE"):
|
||||
return {"error": f"Unsupported method: {method}", "exit_code": 1}
|
||||
if any(method == m and path.startswith(p) for m, p in _APP_API_BLOCKLIST_METHOD_PATH):
|
||||
if path.startswith("/api/tools"):
|
||||
return {"error": "Tool policy cannot be replaced from chat. Re-enable tools in Settings > Agent Tools; use manage_settings to list or disable them.", "exit_code": 1}
|
||||
if path.startswith("/api/mcp/servers"):
|
||||
return {"error": "MCP server and tool policy cannot be changed from chat. Ask the user to change it in Settings > Integrations.", "exit_code": 1}
|
||||
if "/api/email/accounts" in path:
|
||||
return {"error": "Don't use /api/email/accounts via app_api — it is owner-filtered in tool context and may return empty. Use the `list_email_accounts` email tool, then pass `account` to list_emails/read_email.", "exit_code": 1}
|
||||
if "/api/cookbook/packages/install" in path:
|
||||
|
||||
Reference in New Issue
Block a user