Submit #844480: DeepMyst Mysti 0.4.0 Authorization Bypass / Identity Spoofinginfo

TitleDeepMyst Mysti 0.4.0 Authorization Bypass / Identity Spoofing
Description## Vulnerability Title Authorization Bypass via Hash-Key Confusion in OpenClaw ChannelBridge Contact Tracking ## Affected Component `src/managers/ChannelBridge.ts` Repository: https://github.com/DeepMyst/Mysti ## Summary An attacker with access to another connected OpenClaw channel can craft an inbound channel event whose `sender` matches a previously contacted person, causing identity-key reuse across channels. This leads to unauthorized inbound message routing into Mysti's agent context, negatively impacting users who have multiple OpenClaw channels connected. ## Technical Details The vulnerability occurs because `ChannelBridge` computes an application-level identity key over only the normalized sender/contact identifier and then uses that key as an inbound authorization gate. The key does not include all security-relevant fields (like channel identity), so two inbound messages that are not security-equivalent can be treated as the same contacted identity. **Where the Identity Key is Computed** In `src/managers/ChannelBridge.ts`, the contact is tracked using only a normalized string of the `nameOrPhone`: ```ts private _trackContact(nameOrPhone: string, channel: string): void { const key = this._normalizeContactId(nameOrPhone); this._trackedContacts.set(key, { identifier: key, channel, sentAt: Date.now(), }); } private _normalizeContactId(id: string): string { const trimmed = id.trim(); if (trimmed.startsWith('+')) { return trimmed; } // E.164 phone return trimmed.toLowerCase(); } ``` **Vulnerable Authorization Check** When an inbound message arrives, `_isTrackedConversation` is used as an authorization gate to route the message. However, the check ignores the `_channelType` parameter and only verifies if the normalized sender string exists in the tracked contacts map: ```ts private _isTrackedConversation(sender: string | undefined, _channelType: string): boolean { // ... const senderNorm = this._normalizeContactId(sender); for (const [key, contact] of this._trackedContacts) { // ... TTL checks ... if (key === senderNorm) { return true; } if (senderNorm.includes(key) || key.includes(senderNorm)) { return true; } } return false; } ``` Because the same display name or phone-like sender string can exist across multiple channels (e.g., WhatsApp vs. Telegram), cross-channel equality of the sender string is enough to pass the gate. **How the Attacker Constructs a Conflicting Object** Victim-side tracked contact: ```json { "nameOrPhone": "Bob", "channel": "whatsapp", "channelId": "wa-1" } ``` Attacker-controlled inbound message: ```json { "sender": "Bob", "channelType": "telegram", "channelId": "tg-1", "content": "Yes, deploy now" } ``` Both produce the same identity key (`bob`). They are not security-equivalent, but the system treats them as the same identity. ## Impact This vulnerability allows attackers to: - Spoof replies from a previously contacted person across channels. - Inject attacker-controlled content into Mysti's agent context as a trusted inbound channel message. - Answer pending channel questions or cancel running agent tasks using `stop` or `cancel` commands. *(Note: The attack window lasts until the tracked contact's in-memory TTL expires, which defaults to two hours).* ## Proof of Concept The following Node.js script demonstrates how the vulnerable logic treats cross-channel sender equality as identity equivalence. ```js #!/usr/bin/env node function normalizeContactId(id) { const trimmed = id.trim(); return trimmed.startsWith("+") ? trimmed : trimmed.toLowerCase(); } const trackedContacts = new Map(); function trackContact(nameOrPhone, channel) { const key = normalizeContactId(nameOrPhone); trackedContacts.set(key, { identifier: key, channel, sentAt: Date.now() }); } function isTrackedConversation(sender, channelType) { if (!sender) return false; const senderNorm = normalizeContactId(sender); for (const [key] of trackedContacts) { if (key === senderNorm || senderNorm.includes(key) || key.includes(senderNorm)) return true; } return false; } const victim = { nameOrPhone: "Bob", channel: "whatsapp", channelId: "wa-1" }; const attacker = { sender: "Bob", channelType: "telegram", channelId: "tg-1", content: "Yes, deploy now" }; // Track legitimate victim trackContact(victim.nameOrPhone, victim.channel); // Attacker sends message from a different channel const accepted = isTrackedConversation(attacker.sender, attacker.channelType); console.log("victim key: ", normalizeContactId(victim.nameOrPhone)); console.log("attacker key:", normalizeContactId(attacker.sender)); console.log("accepted: ", accepted); if (accepted) { console.log(`[Via Telegram from Bob]: ${attacker.content}`); console.log("Security invariant broken: cross-channel sender equality was treated as identity equivalence."); } ``` *Observed output confirms that the attacker's message from Telegram is accepted based on the WhatsApp tracking entry.* ## Remediation Bind inbound authorization to a channel-scoped identity rather than the sender text alone. Example implementation direction: ```ts // In src/managers/ChannelBridge.ts // Include channel identity in the tracked-contact key. const key = `${channelIdOrType}:${this._normalizeContactId(nameOrPhone)}`; ``` Additional mitigations: 1. Complete Field Coverage: Include `channelId`, `channelType`, and stable provider contact IDs (when available) in the identity verification logic. 2. Domain Separation: Separate identity namespaces strictly across channels and providers. 3. Read-Time Revalidation: Ensure that the inbound event's channel-scoped identity explicitly matches the outbound tracked identity before routing. ## References - Vulnerable contact tracking: `https://github.com/DeepMyst/Mysti/blob/bce0d2ba7904c056c576cf94db817635421d1f41/src/managers/ChannelBridge.ts#L865-L872` - Vulnerable inbound authorization check: `https://github.com/DeepMyst/Mysti/blob/bce0d2ba7904c056c576cf94db817635421d1f41/src/managers/ChannelBridge.ts#L880-L899` - Inbound routing sink: `https://github.com/DeepMyst/Mysti/blob/bce0d2ba7904c056c576cf94db817635421d1f41/src/managers/ChannelBridge.ts#L687-L758`
Source⚠️ https://github.com/DeepMyst/Mysti/issues/42
User
 dem0000 (UID 98390)
Submission06/01/2026 05:12 (28 days ago)
Moderation06/29/2026 06:51 (28 days later)
StatusAccepted
VulDB entry374594 [DeepMyst Mysti 0.4.0 Contact Tracking ChannelBridge.ts _isTrackedConversation _channelType improper authorization]
Points20

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!