mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-01-30 06:12:06 +00:00
fix: revert unsafe permission changes from PR #78
Security fixes to restore defense-in-depth after merging PR #78: **client.py:** - Revert permission mode from "bypassPermissions" to "acceptEdits" - Remove redundant web_tools_auto_approve_hook from PreToolUse hooks - Remove unused import of web_tools_auto_approve_hook **security.py:** - Remove web_tools_auto_approve_hook function (was redundant and returned {} for ALL tools, not just WebFetch/WebSearch) **server/services/spec_chat_session.py:** - Restore allowed_tools restriction: [Read, Write, Edit, Glob, WebFetch, WebSearch] - Revert permission mode from "bypassPermissions" to "acceptEdits" - Keeps setting_sources=["project", "user"] for global skills access **ui/src/components/AgentAvatar.tsx:** - Remove unused getMascotName export to fix React Fast Refresh warning - File now only exports AgentAvatar component as expected The bypassPermissions mode combined with unrestricted tool access in spec_chat_session.py created a security gap where Bash commands could execute without validation (sandbox disabled, no bash_security_hook). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient
|
||||
from claude_agent_sdk.types import HookMatcher
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from security import bash_security_hook, web_tools_auto_approve_hook
|
||||
from security import bash_security_hook
|
||||
|
||||
# Load environment variables from .env file if present
|
||||
load_dotenv()
|
||||
@@ -181,7 +181,7 @@ def create_client(
|
||||
security_settings = {
|
||||
"sandbox": {"enabled": True, "autoAllowBashIfSandboxed": True},
|
||||
"permissions": {
|
||||
"defaultMode": "bypassPermissions", # Auto-approve all tools
|
||||
"defaultMode": "acceptEdits", # Auto-approve edits within allowed directories
|
||||
"allow": permissions_list,
|
||||
},
|
||||
}
|
||||
@@ -273,7 +273,6 @@ def create_client(
|
||||
hooks={
|
||||
"PreToolUse": [
|
||||
HookMatcher(matcher="Bash", hooks=[bash_security_hook]),
|
||||
HookMatcher(matcher="WebFetch|WebSearch", hooks=[web_tools_auto_approve_hook]),
|
||||
],
|
||||
},
|
||||
max_turns=1000,
|
||||
|
||||
22
security.py
22
security.py
@@ -309,28 +309,6 @@ def get_command_for_validation(cmd: str, segments: list[str]) -> str:
|
||||
return ""
|
||||
|
||||
|
||||
async def web_tools_auto_approve_hook(input_data, tool_use_id=None, context=None):
|
||||
"""
|
||||
Pre-tool-use hook that auto-approves WebFetch and WebSearch tools.
|
||||
|
||||
Workaround for Claude Code bug where these tools are auto-denied in dontAsk mode.
|
||||
See: https://github.com/anthropics/claude-code/issues/11881
|
||||
|
||||
Args:
|
||||
input_data: Dict containing tool_name and tool_input
|
||||
tool_use_id: Optional tool use ID
|
||||
context: Optional context
|
||||
|
||||
Returns:
|
||||
Empty dict to allow (auto-approve)
|
||||
"""
|
||||
tool_name = input_data.get("tool_name", "")
|
||||
if tool_name in ("WebFetch", "WebSearch"):
|
||||
# Return empty dict = allow/approve the tool
|
||||
return {}
|
||||
return {}
|
||||
|
||||
|
||||
async def bash_security_hook(input_data, tool_use_id=None, context=None):
|
||||
"""
|
||||
Pre-tool-use hook that validates bash commands using an allowlist.
|
||||
|
||||
@@ -181,8 +181,15 @@ class SpecChatSession:
|
||||
# System prompt loaded from CLAUDE.md via setting_sources
|
||||
# Include "user" for global skills and subagents from ~/.claude/
|
||||
setting_sources=["project", "user"],
|
||||
# No allowed_tools restriction - full access to all tools, skills, subagents
|
||||
permission_mode="bypassPermissions", # Auto-approve all tools
|
||||
allowed_tools=[
|
||||
"Read",
|
||||
"Write",
|
||||
"Edit",
|
||||
"Glob",
|
||||
"WebFetch",
|
||||
"WebSearch",
|
||||
],
|
||||
permission_mode="acceptEdits", # Auto-approve file writes for spec creation
|
||||
max_turns=100,
|
||||
cwd=str(self.project_dir.resolve()),
|
||||
settings=str(settings_file.resolve()),
|
||||
|
||||
@@ -595,9 +595,3 @@ export function AgentAvatar({ name, state, size = 'md', showName = false }: Agen
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Get mascot name by index (cycles through available mascots)
|
||||
export function getMascotName(index: number): AgentMascot {
|
||||
const mascots = Object.keys(MASCOT_SVGS) as AgentMascot[]
|
||||
return mascots[index % mascots.length]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user