Skip to content

feat(tools): gate network egress behind a web_fetch tool category (closes #310)#311

Merged
haofeif merged 1 commit into
awslabs:mainfrom
call-me-ram:feat/claude-code-web-fetch-tool-mapping
Jun 19, 2026
Merged

feat(tools): gate network egress behind a web_fetch tool category (closes #310)#311
haofeif merged 1 commit into
awslabs:mainfrom
call-me-ram:feat/claude-code-web-fetch-tool-mapping

Conversation

@call-me-ram

@call-me-ram call-me-ram commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

What & why

Closes #310.

CAO's tool-restriction vocabulary did not map providers' network tools (Claude Code's WebFetch/WebSearch, Gemini's web_fetch/google_web_search) to any CAO category. As documented in docs/tool-restrictions.md Known Limitation #1, they stayed unrestricted even when allowedTools was set — a read-only reviewer or orchestration-only supervisor could still fetch arbitrary URLs, an exfiltration / SSRF surface the restriction system otherwise closes.

This adds a web_fetch category so network access becomes governable.

Changes

  • tool_mapping.pyclaude_code: web_fetch → [WebFetch, WebSearch]; gemini_cli: web_fetch → [web_fetch, google_web_search]. A profile/role without web_fetch now emits the native disallow flags for those tools.
  • constants.pydeveloper role default gains web_fetch, so the full-access role (and the no-role/no-allowedTools default, which resolves to developer) keeps network access. supervisor/reviewer stay off the network — and since they also lack execute_bash (curl), they have no egress channel at all.
  • terminal_service.py — launch-time guard: kimi_cli/codex have no native tool-blocking (soft/prompt-level only), so creating a restricted terminal on them now logs a loud warning to route restricted or write-capable roles to a hard-enforcement provider.
  • docs/tool-restrictions.md — vocabulary + translation tables, role table, default-behavior text, sample confirmation prompt, and a rewritten Known Limitation Initial Launch #1.
  • tests — new web_fetch cases (claude + gemini mapping, egress-channel blocking, copilot no-op).

subagent/Task — intentionally not a separate category

The original limitation note also mentioned subagent. Task is already gated: it's deliberately folded into execute_bash (see the comment block in tool_mapping.py and TestClaudeCodeSubagentEscape) because a Task subagent spawns with its own full toolset and can run shell. Exposing subagent as an independently-grantable category would let a profile grant it without execute_bash and re-open that privilege-escalation escape. So this PR leaves Task bundled into execute_bash.

Behavior change / compatibility

Profiles that hard-code the old developer list (["@builtin", "fs_*", "execute_bash", "@cao-mcp-server"]) rather than using role: developer will now have the network tools blocked. They opt back in by adding web_fetch (or *). This is the intended consequence of making web access governable. The role: developer path and the unrestricted default are unaffected. For providers without a network entry (Copilot), an unknown web_fetch token is a harmless no-op.

Testing

  • uv run pytest test/utils/test_tool_mapping.py — passes (includes the new web_fetch cases).
  • uv run pytest test/services/test_terminal_service*.py test/mcp_server/test_resolve_child_allowed_tools.py test/cli/commands/test_launch.py — passes (covers the launch guard + tool resolution).
  • Mapping/complement logic is unit-proven; runtime enforcement of --disallowedTools WebFetch on Claude Code is best verified with the live-CLI e2e (test/e2e/test_allowed_tools.py).

CAO's tool-restriction vocabulary did not map providers' network tools, so
they stayed unrestricted even when allowedTools was set — a read-only reviewer
or orchestration-only supervisor could still reach the network. Add a web_fetch
category so network access is governable across providers.

- claude_code: web_fetch -> [WebFetch, WebSearch]; gemini_cli: web_fetch ->
  [web_fetch, google_web_search]. A profile/role without web_fetch now blocks
  those tools.
- developer role gains web_fetch (full-access role and the no-role default keep
  network access — no silent regression); supervisor/reviewer stay off the
  network, removing their egress channel entirely (they also lack execute_bash,
  i.e. curl).
- subagent (Task) is intentionally NOT a separate category: it stays folded into
  execute_bash, since a Task subagent spawns with its own full toolset and can
  run shell — a standalone subagent grant would re-open that escape.
- Launch-time guard: kimi_cli/codex have no native tool-blocking (soft/prompt
  enforcement only), so creating a restricted terminal on them logs a loud
  warning to route restricted/write-capable roles to hard-enforcement providers.
- web_fetch is a no-op for providers without a network entry (copilot), keeping
  the vocabulary universal without changing their behavior.
- Update docs/tool-restrictions.md vocabulary/translation tables and Known
  Limitation #1; extend test/utils/test_tool_mapping.py.

Closes awslabs#310
@call-me-ram call-me-ram force-pushed the feat/claude-code-web-fetch-tool-mapping branch from 70fbf35 to ccca369 Compare June 17, 2026 13:06
@call-me-ram call-me-ram changed the title feat(tools): map Claude Code WebFetch/WebSearch via a web_fetch category (closes #310) feat(tools): gate network egress behind a web_fetch tool category (closes #310) Jun 17, 2026
@haofeif haofeif requested a review from Copilot June 19, 2026 00:07
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@bc4d837). Learn more about missing BASE report.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #311   +/-   ##
=======================================
  Coverage        ?   87.23%           
=======================================
  Files           ?       92           
  Lines           ?    10976           
  Branches        ?        0           
=======================================
  Hits            ?     9575           
  Misses          ?     1401           
  Partials        ?        0           
Flag Coverage Δ
unittests 87.23% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a new CAO tool category (web_fetch) to make provider network-egress tools governable under CAO’s allowedTools/role restriction system, closing an enforcement gap where some providers’ web tools stayed unrestricted.

Changes:

  • Add web_fetch to the CAO vocabulary and map it to provider-native network tools for Claude Code and Gemini CLI.
  • Update built-in role defaults so developer retains network access while supervisor/reviewer remain network-disabled.
  • Add a launch-time warning when attempting restricted policies on providers that only support prompt-level (soft) enforcement, and update docs/tests accordingly.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/utils/test_tool_mapping.py Adds unit tests for web_fetch mapping and updates developer expectations.
test/e2e/test_allowed_tools.py Updates e2e metadata test to include web_fetch in the developer allowed-tools string.
src/cli_agent_orchestrator/utils/tool_mapping.py Adds web_fetch mappings for claude_code and gemini_cli provider tool translation.
src/cli_agent_orchestrator/services/terminal_service.py Adds soft-enforcement provider warning when restricted allowed_tools is requested.
src/cli_agent_orchestrator/constants.py Extends developer role defaults to include web_fetch and documents vocabulary intent.
docs/tool-restrictions.md Documents web_fetch vocabulary, role defaults, and updated known limitations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# only), so a restricted policy on them is advisory, not enforced.
# Surface that loudly at launch so operators route restricted or
# write-capable roles to hard-enforcement providers instead.
if provider in SOFT_ENFORCEMENT_PROVIDERS and allowed_tools and "*" not in allowed_tools:

@haofeif haofeif left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@haofeif haofeif merged commit bcf3fa3 into awslabs:main Jun 19, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] Map Claude Code WebFetch/WebSearch to a CAO web_fetch tool category (closes part of tool-restrictions Known Limitation #1)

4 participants