fix(backend): allow Read tool for workspace-scoped paths (tool-results/tool-outputs)

The security hooks were blocking Read unconditionally because it was in
BLOCKED_TOOLS. However, the SDK needs Read to access tool-results/ and
tool-outputs/ directories for oversized result handling. Fix by adding
Read to WORKSPACE_SCOPED_TOOLS and checking workspace scope before the
blocked-tools list, so Read is allowed within the workspace but still
blocked for arbitrary paths.
This commit is contained in:
majdyz
2026-04-12 09:05:54 +00:00
parent c228b2c4c6
commit ab07e55635
2 changed files with 14 additions and 9 deletions

View File

@@ -101,6 +101,13 @@ def _validate_tool_access(
Returns:
Empty dict to allow, or dict with hookSpecificOutput to deny
"""
# Workspace-scoped tools: allowed only within the SDK workspace directory.
# Check this BEFORE the blocked-tools list because Read is blocked in
# general but must remain accessible for tool-results/tool-outputs paths
# that the SDK uses internally for oversized result handling.
if tool_name in WORKSPACE_SCOPED_TOOLS:
return _validate_workspace_path(tool_name, tool_input, sdk_cwd)
# Block forbidden tools
if tool_name in BLOCKED_TOOLS:
logger.warning(f"Blocked tool access attempt: {tool_name}")
@@ -110,10 +117,6 @@ def _validate_tool_access(
"Use the CoPilot-specific MCP tools instead."
)
# Workspace-scoped tools: allowed only within the SDK workspace directory
if tool_name in WORKSPACE_SCOPED_TOOLS:
return _validate_workspace_path(tool_name, tool_input, sdk_cwd)
# Check for dangerous patterns in tool input
# Use json.dumps for predictable format (str() produces Python repr)
input_str = json.dumps(tool_input) if tool_input else ""

View File

@@ -778,11 +778,13 @@ BLOCKED_TOOLS = {
# Tools allowed only when their path argument stays within the SDK workspace.
# The SDK uses these to handle oversized tool results (writes to tool-results/
# files, then reads them back) and for workspace file operations.
# Read, Write, and Edit are NOT included: they are in
# SDK_DISALLOWED_TOOLS because the SDK built-in versions are fully
# replaced by MCP equivalents. Including them here would conflict
# with the disallow list.
WORKSPACE_SCOPED_TOOLS = {"Glob", "Grep"}
# Read is included because the SDK reads back oversized tool results from
# tool-results/ and tool-outputs/ directories. It is also in
# SDK_DISALLOWED_TOOLS (which controls the SDK's disallowed_tools config),
# but the security hooks check workspace scope BEFORE the blocked list
# so that these internal reads are permitted.
# Write and Edit are NOT included: they are fully replaced by MCP equivalents.
WORKSPACE_SCOPED_TOOLS = {"Glob", "Grep", "Read"}
# Dangerous patterns in tool inputs
DANGEROUS_PATTERNS = [