-
Notifications
You must be signed in to change notification settings - Fork 503
Description
Summary
PreToolUse hooks currently require permissionDecision: "allow" to apply updatedInput modifications. This prevents using hooks for input sanitization while preserving the normal permission flow (Deny Rules → Allow Rules → Ask Rules → canUseTool).
Use Case
We're building a multi-tenant Claude SDK application where we need to:
- Pass
ANTHROPIC_API_KEYto the SDK subprocess for API authentication - Prevent Bash tool commands from accessing sensitive environment variables
Our security approach:
- Intercept Bash commands via PreToolUse hook
- Prepend
unset ANTHROPIC_API_KEY FACETS_TOKEN ...;to commands - Let the normal permission flow decide whether to allow/deny/ask
Current Behavior
# Hook returns only updatedInput (no permissionDecision)
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"updatedInput": {
"command": f"unset SENSITIVE_VAR; {original_command}"
}
}
}Result: updatedInput is ignored, original command runs unmodified.
Expected Behavior
Hook should be able to modify input AND continue to normal permission flow:
PreToolUse Hook (modify input) → Deny Rules → Allow Rules → Ask Rules → canUseTool
↓
updatedInput applied
Current Workarounds (All Have Drawbacks)
| Approach | Problem |
|---|---|
Hook + permissionDecision: "allow" |
Auto-allows all Bash, bypasses user confirmation |
canUseTool callback |
Bypassed when Allow Rules match ("Allow for Session") |
| Don't pass API key to subprocess | SDK can't authenticate API calls |
Proposed Solution
Support updatedInput without permissionDecision:
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"updatedInput": {"command": secured_command},
# No permissionDecision → continue to Deny/Allow/Ask rules with modified input
}
}Alternative Solutions
CLI Argument for API Key Authentication
Support passing ANTHROPIC_API_KEY via CLI argument instead of environment variable:
claude --api-key "sk-ant-..." [other options]Or via SDK options:
ClaudeAgentOptions(
api_key="sk-ant-...", # Passed as CLI arg, NOT as env var
env={}, # No sensitive vars in subprocess environment
)Benefits:
- CLI process authenticates using the argument
- Argument is NOT inherited by child processes (unlike env vars)
- Bash subprocesses never see the API key
- No hooks or input modification needed
This follows the security principle of least privilege - authentication credentials are scoped to the process that needs them, not leaked to all descendants.
Environment
- Claude Code CLI version: 2.x
- claude-agent-sdk (Python): 0.1.6
- Platform: Linux/macOS
Impact
This limitation affects any SDK integrator who needs to:
- Sanitize tool inputs for security
- Transform tool parameters based on context
- Protect sensitive credentials from Bash tool access
- While still respecting permission rules and user confirmations