#20251: fix: sanitize error messages to prevent internal details and PII from leaking to end users
channel: whatsapp-web
agents
size: L
trusted-contributor
## Summary
Internal error details were leaking to end users via messaging channels through multiple code paths. This PR hardens error sanitization across the entire outbound error pipeline — addressing **10 open issues** spanning LLM errors, media errors, auth leaks, tool errors, stream parse failures, and post-compaction corruption.
### Leak vectors fixed
| Vector | What leaked | Issue(s) |
|--------|------------|----------|
| LLM transient errors | Raw `api_error`, `server_error`, `internal_error` JSON with request_ids | #20250 |
| Media fetch errors | URLs, redirect targets, HTTP response body with conversation metadata, phone numbers, group IDs | #20279 |
| Auth/permission errors | `authentication_error`, `permission_error` with credential details | #18937 |
| Failover wrapper messages | `FailoverError:` and `All models failed (N):` exposing provider/model chains | #20250 |
| `invalid_request_error` paths | `messages.N.content.N.thinking.signature: Field required` — session internals | #16825 |
| Tool error warnings | Stack traces, file paths, long internal error text in `⚠️ tool failed:` messages | #17828 |
| SSE/JSON stream parse errors | `Bad control character in string literal in JSON at position N` | #14321 |
| Post-compaction orphaned tool calls | `No tool call found for function call output with call_id toolu01...` | #16948 |
| Fallback catch-all | JSON payloads, HTML error pages, stack traces, and long strings slipping past specific checks | #12928, #11038 |
| `formatRawAssistantErrorForUi` | Raw `HTTP code`, error `type`, and `request_id` exposed in parsed API errors | #7867 |
### Changes
**`src/agents/pi-embedded-helpers/errors.ts`**
- `isTransientApiError()` — detect transient server errors from API JSON payloads
- `isAuthApiError()` — detect 401/403 auth errors from API payloads
- `isFailoverWrapperMessage()` — detect failover wrapper strings
- `invalid_request_error` handler: suppress message path indices (`messages.N.content.N...`) and `thinking.signature` errors
- SSE/JSON parse errors (`Bad control character`, `Unexpected token`, `JSON at position`) → generic message
- Orphaned tool call errors (`No tool call found for call_id`) → format error message
- `formatRawAssistantErrorForUi()`: strip `request_id` and HTTP prefix from parsed errors; catch-all suppresses JSON, HTML, stack traces, and long strings
- `formatAssistantErrorText()`: same hardening for the catch-all fallback path
**`src/agents/pi-embedded-runner/run/payloads.ts`**
- Sanitize tool error text — strip stack traces, file paths, and long error text from `⚠️ tool failed:` user-facing warnings
**`src/web/auto-reply/deliver-reply.ts`**
- Strip `err.message` from `⚠️ Media failed` warning — always shows just `⚠️ Media failed.`
### Tests
- New test file: `errors.sanitize-leak-vectors.test.ts` (16 tests covering all new sanitization paths)
- Updated TUI formatter tests for new sanitized output
- Updated deliver-reply test to assert error internals don't leak
- All 7591+ tests passing
**No debugging information is lost** — all raw errors remain in server logs (`console.warn`, `whatsappOutboundLog`, `replyLogger`).
### Supersedes
- PR #18970 (`fix/issue-18937`) — narrower fix for auth error leaks, fully covered here
### Related issues
Fixes #20250
Fixes #20279
Fixes #18937
Fixes #16825
Fixes #14321
Fixes #16948
Addresses leak vectors reported in: #7867, #9951, #11038, #12928, #17828
Related architecture discussion: #16521, #16673
Most Similar PRs
#22088: fix(web): sanitize media errors to prevent PII leak
by ashiabbott · 2026-02-20
75.9%
#18970: Fix #18937: Don't leak API errors to user channel
by jwchmodx · 2026-02-17
71.4%
#20537: feat: centralized outbound message sanitization gate
by echoVic · 2026-02-19
71.4%
#23175: feat(security): runtime safety — transcript retention, tool call bu...
by ihsanmokhlisse · 2026-02-22
70.8%
#9173: Fix: Improve error messaging for API rate limits and billing errors
by vishaltandale00 · 2026-02-04
69.3%
#8103: fix(tts): sanitize API keys from error messages
by yubrew · 2026-02-03
69.2%
#19235: fix(telegram): tool error warnings no longer overwrite streamed rep...
by gatewaybuddy · 2026-02-17
69.0%
#4009: fix(agent): sanitize messages after orphan user repair
by drag88 · 2026-01-29
68.7%
#20301: Security: scrub untrusted metadata from user-facing replies
by ashishc2503 · 2026-02-18
68.4%
#19406: fix(heartbeat): filter error payloads from heartbeat reply selection
by namabile · 2026-02-17
68.2%