anthropics / anthropics/claude-agent-sdk-python
[SECURITY] Edit tool reads file content before PreToolUse hook validation, allowing content probing
- Ngôn ngữ chính
- Python
- Star
- 8.1k
- Fork
- 1.3k
- Merge trung bình
- 2 ngày 31 phút
- Pull request đã merge (30 ngày)
- 1
Mô tả
## Summary
The Edit tool reads file content to validate `old_string` parameter **before** PreToolUse hooks are executed. This allows attackers to probe the content of files outside allowed directories by observing error messages, even when PreToolUse hooks are configured to block such access.
## Vulnerability Details
### Current Behavior
When an Edit operation is attempted with an `old_string` that:
1. Has multiple matches in the file → Returns "Found X matches" error
2. Does not exist in the file → Returns "String not found" error
**The file content is read before PreToolUse hooks can validate the file path.**
### Attack Vector
An attacker can probe file content outside allowed directories:
1. **Test for string existence**: Use `old_string="secret_api_key"` → If "String not found", the string doesn't exist; if "Found X matches", it does
2. **Enumerate file content**: Use common strings (`"password"`, `"token"`, `"key"`) to discover what's in the file
3. **Bypass security boundary**: Even though the edit is ultimately blocked, the information leak has already occurred
### Proof of Concept
1. Configure a PreToolUse hook to restrict file access to a specific directory:
```python
async def edit_only_cwd_hook(hook_input: HookInput, _session_id: str | None, _ctx: HookContext):
cwd = Path(hook_input["cwd"])
tool_input = hook_input.get("tool_input", {})
file_path_str = tool_input.get("file_path", "")
try:
file_path.relative_to(cwd)
except ValueError:
return SyncHookJSONOutput(decision="block", reason="...")
return SyncHookJSONOutput()
hooks = {
"PreToolUse": [
HookMatcher(matcher="Edit", hooks=[edit_only_cwd_hook])
]
}
```
2. Attempt to edit a file **outside** the allowed directory with a unique string:
```
Edit tool:
file_path: "/etc/passwd" (or any restricted file)
old_string: "root"
new_string: "hacked"
```
3. **Result**: Returns "Found X matches of the string to replace..." error
**The error message confirms the string "root" exists in the file, leaking information about file content.**
### Expected Behavior
PreToolUse hooks should be executed **before** any file content is read. The validation order should be:
1. ✅ PreToolUse hook validates file path
2. ✅ Hook blocks access to restricted paths
3. ❌ File content is never read (currently this happens before step 1)
## Security Impact
- **Information disclosure**: Attackers can probe file content character by character
- **Security boundary bypass**: Path-based access control is ineffective
- **Credential discovery**: Can detect presence of secrets, API keys, passwords in restricted files
## Affected Components
- Tool: `Edit`
- Hook Event: `PreToolUse`
- May also affect: `Write` (similar pattern)
## Environment
- Claude Code version 2.1.50
- Claude Agent SDK Version: 0.1.39
- Platform: macOS 26.3
## Related Issues (Claude Code Repository)
- [anthropics/claude-code#24908](https://github.com/anthropics/claude-code/issues/24908) - PostToolUse/PostToolUseFailure not fired for `` responses
- [anthropics/claude-code#21460](https://github.com/anthropics/claude-code/issues/21460) - PreToolUse hooks not enforced on subagent tool calls
## Suggested Fix
The PreToolUse hook should be triggered and validated **before** the Edit tool reads the file content. Only after the hook approves the operation should the file be accessed to validate `old_string`.
---
## Alternative: Temporary Workaround
For users affected by this issue, consider:
1. **Disable Edit tool entirely** - Only allow Write tool (may have similar issue, needs verification)
2. **Use MCP filesystem tools** with path restrictions instead of built-in tools
3. **Implement additional sandboxing** at the OS level (e.g., containerization)
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Đánh giá
Issue này chưa được đánh giá.