# Vulnerability Summary ## Overview This vulnerability involves a cache key design issue in the Zalo webhook, leading to cross-account cache pollution. Specifically, when the `path`/`account` values of different accounts conflict in the colon-separated key, it may cause events to be incorrectly deduplicated, resulting in the loss of important information. ## Impact Scope - **Affected Component**: Zalo webhook module - **Impact Scenario**: In multi-account deployment environments, improper cache key design may lead to incorrect deduplication of events across different accounts. - **Potential Risk**: Important events may be ignored, affecting the normal operation of business logic. ## Remediation Plan 1. **Update Cache Key Design**: Change the cache key from a simple `path`/`account` combination to a more complex structure to ensure that events from different accounts do not conflict. 2. **Code Modifications**: - Modify the `buildReplayEventCacheKey` function to include considerations for `target.account.accountId`, `update.event_name`, `childId`, `senderId`, and `messageId`. - Modify the `isReplayEvent` function to use the new cache key for event deduplication checks. ## POC Code ```typescript // Modified buildReplayEventCacheKey function function buildReplayEventCacheKey( target: ZaloWebhookTarget, update: ZaloUpdate, messageId: string ): string { const chatId = update.message?.chat?.id ?? ""; const senderId = update.message?.from?.id ?? ""; return JSON.stringify([ target.path, target.account.accountId, update.event_name, chatId, senderId, messageId ].join(":")); } // Modified isReplayEvent function function isReplayEvent( target: ZaloWebhookTarget, update: ZaloUpdate, nowMs: number ): boolean { const messageId = update.message?.message_id; if (!messageId) { return false; } const chatId = update.message?.chat?.id ?? ""; const senderId = update.message?.from?.id ?? ""; // Scope replay dedupe to the authenticated target and the message origin so // reused message ids in other chats or from other senders do not collide. const key = [ target.path, target.account.accountId, update.event_name, chatId, senderId, messageId, "" ].join(":"); const key = buildReplayEventCacheKey(target, update, messageId); return recentWebhookEvents.check(key, nowMs); } ``` ## Additional Information - **Submitters**: pgondhi987 and jacobtomlinson - **Submission Time**: last month - **Related Issue**: #59387