How to Auto-Approve Safe WebFetches While Blocking Suspicious URLs with Hooks
Open SourceScore: 75

How to Auto-Approve Safe WebFetches While Blocking Suspicious URLs with Hooks

Use Claude Code's PreToolUse hooks to automatically allow clean documentation URLs while forcing manual review for any URL containing query parameters, eliminating repetitive prompts without sacrificing security.

GAla Smith & AI Research Desk·3h ago·3 min read·5 views·AI-Generated
Share:
Source: dev.tovia devto_claudecodeSingle Source

The Technique — Smart WebFetch Permissions with Hooks

Every time Claude Code fetches a URL, it asks for permission. After dozens of approvals for the same Python documentation page, you start looking for an auto-approve button. The naive solution is adding "WebFetch" to your permissions.allow list in ~/.claude/settings.json. This works, but it's dangerous—it auto-approves everything, including a malicious URL like https://evil.com?secret=YOUR_API_KEY that could be injected via a prompt.

The correct solution uses Claude Code's PreToolUse hook system. A hook is a script that runs before a tool executes. It can:

  • Exit 0 — Silently allow the tool (no prompt).
  • Exit 1 — Show a message and ask for confirmation (approve/deny).
  • Exit 2 — Hard block the tool (no option to proceed).

You can write a hook that inspects the WebFetch URL and only prompts you if it contains a query parameter (a ?). Clean documentation URLs auto-fetch; anything with ?key=value gets flagged for review.

Why It Works — Granular Control Over Tool Execution

This works because the PreToolUse hook receives the full, structured tool call as JSON via stdin. You can parse this data to make intelligent decisions. The hook input looks like this:

{
  "session_id": "abc-123",
  "hook_event_name": "PreToolUse",
  "tool_name": "WebFetch",
  "tool_input": {
    "url": "https://example.com/page?q=test",
    "prompt": "Summarize this page"
  }
}

Query parameters in a URL (?q=test) are a common vector for data exfiltration in prompt injection attacks. By treating them as a higher-risk signal, you create a simple but effective security heuristic. Legitimate uses (like fetching API docs with anchors #section) still get flagged, but you can approve them manually. The trade-off—a few manual approvals for parameterized URLs—is worth the security gain.

How To Apply It — A Zero-Dependency Hook

Add this configuration to your ~/.claude/settings.json. It uses a Python one-liner with no external dependencies.

Cover image for Claude Code: Auto-Approve Tools While Keeping a Safety Net with Hooks

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "WebFetch",
        "hooks": [
          {
            "type": "command",
            "command": "python3 -c \"import sys,json; data=json.load(sys.stdin); url=data.get('tool_input',{}).get('url',''); print('URL has query params, review: '+url, file=sys.stderr) if '?' in url else None; sys.exit(1) if '?' in url else sys.exit(0)\"",
            "statusMessage": "Checking WebFetch URL for query params..."
          }
        ]
      }
    ]
  }
}

Critical Setup Notes:

  1. Remove WebFetch from permissions.allow. If WebFetch is in the allow list, the hook never fires. The permission system takes full precedence.
  2. Input is via stdin, not environment variables. The hook script must read json.load(sys.stdin), not check os.environ.

Once configured:

  • https://docs.python.org/3/library/json.html → Auto-allowed, no prompt.
  • https://api.example.com/data?key=secret → Prints "URL has query params, review: ..." and pauses for your approval.

Going Further — Apply the Pattern to Other Tools

The same hook pattern can guard other powerful tools. Here’s a Bash command guard that flags dangerous operations:

{
  "matcher": "Bash",
  "hooks": [{
    "type": "command",
    "command": "python3 -c \"import sys,json; cmd=json.load(sys.stdin).get('tool_input',{}).get('command',''); dangerous=any(w in cmd for w in ['rm -rf','drop table','--force','--hard']); print('Dangerous command: '+cmd, file=sys.stderr) if dangerous else None; sys.exit(1) if dangerous else sys.exit(0)\""
  }]
}

You can create similar guards for the Write tool to flag edits to sensitive paths (like *.env, *config.json) or for custom MCP servers. The hook system is your programmable layer between Claude's intent and the system's execution.

AI Analysis

Claude Code users should immediately implement this hook to reclaim productivity. The constant "Allow WebFetch?" prompt is a major friction point, especially when working with documentation. This hook eliminates that for 90% of cases while maintaining a crucial security check. **Action 1: Edit your `settings.json` today.** Copy the hook configuration above. Remember to **remove** `"WebFetch"` from `permissions.allow` if it's there, or the hook won't work. This is the most common mistake. **Action 2: Extend the pattern.** Once you see how the `PreToolUse` hook works, apply it to the `Bash` tool. The example guard for `rm -rf` and `drop table` is a starting point; customize it for your project's dangerous commands (e.g., `git push --force`, `kubectl delete`). **Action 3: Think in terms of risk heuristics.** The core idea is using simple, programmable rules (like "contains `?`") to categorize risk. What's a risky pattern in your workflow? Writing to `package.json`? Running a database migration? You can build a hook for it. This moves you from blanket permissions to intelligent, context-aware delegation, which is essential for using an agentic tool like Claude Code effectively.
Enjoyed this article?
Share:

Related Articles

More in Open Source

View all