#23271: fix(chat): strip untrusted metadata blocks from Control UI messages
gateway
size: S
## 🤖 AI-Assisted Contribution
This PR was created with AI assistance (Claude). The contributor fully understands the changes and has tested them thoroughly.
---
## Problem
Control UI displays untrusted metadata JSON blocks in the message transcript, causing:
- Visual clutter in chat history
- Potential AI confusion when reading context
- Poor user experience
**Example of leaked metadata:**
```
Conversation info (untrusted metadata):
```json
{ "message_id": "123", "sender": "user" }
```
<actual user message>
```
## Root Cause
1. `src/auto-reply/reply/inbound-meta.ts` generates metadata blocks with prefix like "Conversation info (untrusted metadata):"
2. These blocks are added to user messages in the transcript
3. `stripEnvelope()` only removes `[Channel ...]` style envelopes, not metadata blocks
4. Control UI receives and displays the raw metadata
## Solution
Extend `stripEnvelope()` in `src/shared/chat-envelope.ts` to:
1. Strip traditional `[Channel ...]` envelopes (existing behavior)
2. **NEW:** Strip untrusted metadata blocks using regex pattern
**Regex pattern matches:**
- "Conversation info (untrusted metadata):"
- "Sender (untrusted metadata):"
- "Thread starter (untrusted, for context):"
- "Replied message (untrusted, for context):"
- "Forwarded message context (untrusted metadata):"
- "Chat history since last reply (untrusted, for context):"
## Testing
Added 8 comprehensive tests in `src/gateway/chat-sanitize.test.ts`:
- ✅ Each metadata block type removal
- ✅ Multiple metadata blocks
- ✅ Combined envelope + metadata block
- ✅ False positive prevention
**Test results:**
```
✓ src/gateway/chat-sanitize.test.ts (12 tests) 4ms
✓ src/auto-reply/envelope.test.ts (12 tests) 37ms
✓ src/auto-reply/reply/inbound-meta.test.ts (13 tests) 4ms
Test Files: 3 passed (3)
Tests: 37 passed (37)
```
## Understanding
**How Sparkle version comparison works:**
- Sparkle compares `sparkle:version` as integers
- Pattern: `YYYYMMDD0` (date + trailing zero)
- Incorrect format breaks version ordering
**Why this fix matters:**
- Ensures consistent UI across all channels
- Metadata is for AI context only, not user display
- Prevents information leakage in shared screenshots
Fixes #22686
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Extends `stripEnvelope()` to remove untrusted metadata blocks from Control UI chat history. The implementation adds a regex pattern that matches all 6 metadata block types generated by `buildInboundUserContextPrefix()` (Conversation info, Sender, Thread starter, Replied message, Forwarded message context, and Chat history). The regex correctly handles JSON-encoded content (newlines are escaped, so triple backticks + newlines only match fence closures) and strips multiple blocks using the global flag. Test coverage is comprehensive with 8 new tests covering individual block types, multiple blocks, and interaction with envelope stripping.
<h3>Confidence Score: 5/5</h3>
- Safe to merge - well-tested sanitization improvement with no breaking changes
- The implementation is clean, secure, and well-tested. The regex pattern correctly matches all metadata block types, handles JSON escaping safely (newlines in JSON are escaped so no false matches), and uses appropriate anchors and flags. Test coverage includes all 6 block types, multiple blocks, and envelope interaction. The change is additive (extends existing functionality) with no risk of regression.
- No files require special attention
<sub>Last reviewed commit: e99a2f3</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#20231: fix: strip untrusted metadata blocks from chat history
by MisterGuy420 · 2026-02-18
88.4%
#23312: fix(gateway): strip inbound metadata in chat history sanitization
by SidQin-cyber · 2026-02-22
85.7%
#20301: Security: scrub untrusted metadata from user-facing replies
by ashishc2503 · 2026-02-18
84.4%
#16733: fix(ui): avoid injected newlines when tool output is hidden
by jp117 · 2026-02-15
77.7%
#23073: fix(ui): strip reply directive tags from assistant messages in WebC...
by x4v13r1120 · 2026-02-22
77.0%
#15148: auto-reply: add message_time and compact inbound metadata JSON
by detecti1 · 2026-02-13
76.5%
#17244: fix: strip TTS tags from agent replies before delivery (#14652)
by robbyczgw-cla · 2026-02-15
76.1%
#22832: fix: strip [[reply_to_current]] directive from chat history
by willkriski · 2026-02-21
76.1%
#15395: Auto-reply: strip leaked protocol transcript lines from inbound con...
by kiranjd · 2026-02-13
75.8%
#23144: fix(ui): strip reply directive tags from assistant messages in WebC...
by echoVic · 2026-02-22
75.8%