[BUG] Privacy: Sensitive prompt data exposed in tool_parameters field of claude_code.tool_result open telemetry event despite OTEL_LOG_USER_PROMPTS=0
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Claude Code's documentation states that user prompt content is redacted by default in telemetry data:
https://code.claude.com/docs/en/monitoring-usage#security/privacy-considerations
> Security/privacy considerations
> - User prompt content is redacted by default - only prompt length is recorded
> - To enable user prompt logging, set OTEL_LOG_USER_PROMPTS=1
However, the tool_parameters field in claude_code.tool_result OpenTelemetry events contains paraphrased versions of user prompts, effectively bypassing this privacy protection.
### Example
User prompt:
"Find all occurrences of customer ID 12345 in the repository"
Resulting telemetry event (with OTEL_LOG_USER_PROMPTS=0, the default):
```json
{
"event": {
"name": "tool_result"
},
"tool_name": "Bash",
"tool_parameters": {
"bash_command": "grep",
"full_command": "grep -r \"12345\" . ...",
"description": "Search for exact ID 12345 excluding 123456"
}
}
The tool_paramters field contains sensitive information from the user's prompt despite the redaction setting.
Impact
This creates a privacy and security gap:
1. Sensitive data exposure: Customer IDs, internal paths, API keys, business logic, and other confidential information can leak through the description field
2. Compliance risk: Organizations relying on OTEL_LOG_USER_PROMPTS=0 for GDPR/compliance may unknowingly collect sensitive user data
3. False sense of security: Users expect that disabling OTEL_LOG_USER_PROMPTS prevents prompt content from being logged, but it doesn't
### What Should Happen?
The `tool_parameters` field should respect user privacy settings and not expose prompt content when telemetry logging is disabled.
### Proposed Solutions
#### Option 1: Extend OTEL_LOG_USER_PROMPTS scope (Recommended)
Make `OTEL_LOG_USER_PROMPTS` control **all** prompt-derived content:
```bash
# Default - redacts prompts AND tool descriptions
OTEL_LOG_USER_PROMPTS=0
# Opt-in - includes prompts AND tool descriptions
OTEL_LOG_USER_PROMPTS=1
Result when OTEL_LOG_USER_PROMPTS=0:
{
"tool_name": "Bash",
"tool_parameters": {
"bash_command": "grep",
"full_command": "[REDACTED]",
"description": "[REDACTED]"
}
}
Pros: Intuitive, aligns with user expectations, no new variables needed
---
Option 2: Add separate control
Introduce a new environment variable for tool descriptions:
OTEL_LOG_TOOL_DESCRIPTIONS=0 # Default: redact descriptions
OTEL_LOG_TOOL_DESCRIPTIONS=1 # Include descriptions
Pros: Allows debugging tool usage without logging full prompts, more granular control
---
Recommendation
Option 1 is preferred because:
- Users expect OTEL_LOG_USER_PROMPTS=0 to prevent all prompt content from being logged
- Single setting is easier to understand and maintain
- Aligns with the documented security promise
Error Messages/Logs
Steps to Reproduce
- Configure telemetry with prompt logging disabled
Add to .claude/settings.json:
```json
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_RESOURCE_ATTRIBUTES": "user.name=test_user",
"OTEL_LOG_USER_PROMPTS": "0",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "some url",
"OTEL_EXPORTER_OTLP_HEADERS": "some header",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "some url"
}
}
2. Start Claude Code
claude
3. Send a prompt with sensitive information that will invoke a tool
(example: can you run bash command to do search if there's any details on the person with following information: jonh doe, email jonhdoe@asdf.com? use "bash command" regardless of other options.)
4. Check the telemetry event
5. Look at the claude_code.tool_result event in your telemetry backend. You'll see:
```json
{
"tool_name": "Bash",
"tool_result_size_bytes": "61",
"os": {
"type": "darwin",
"version": "24.6.0"
},
"session": {
"id": "7e80344f-f1ab-4431-a000-d74b15bbd892"
},
"terminal": {
"type": "Apple_Terminal"
},
"duration_ms": "989",
"decision_type": "accept",
"success": "true",
"host": {
"arch": "arm64"
},
"otel": {
"library": {
"name": "com.anthropic.claude_code.events",
"version": "2.1.1"
},
"service": {
"name": "claude-code",
"version": "2.1.1"
},
"user_agent": "OTel-OTLP-Exporter-JavaScript/0.208.0",
"timestamp": "1767995823644000000"
},
"decision_source": "config",
"event": {
"name": "tool_result",
"timestamp": "2026-01-09T21:57:03.644Z"
},
"user": {
"name": "test_user",
"id": "user id"
},
"tool_parameters": "{\"bash_command\":\"grep\",\"full_command\":\"grep -r -i \\\"jonhdoe@asdf.com\\\" . 2>/dev/null | head -20\",\"description\":\"Search for email jonhdoe@asdf.com\"}"
}
Expected: tool_parameters should be [REDACTED] or omitted since OTEL_LOG_USER_PROMPTS=0
Actual: tool_parameters and its description contains sensitive information from the prompt ("jonhdoe@asdf.com")
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.1
Platform
AWS Bedrock
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Happens in both apple terminal and vs code extension.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗