T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/relay_server.py:411- Finding
Unauthenticated Inbox Access Exposes Private Messages and Reply Tokens
- Content
View full analysis
Dict[str, Any]: received_rows = self.conn.execute( """ SELECT d.delivery_id, d.reply_token, d.delivered_at, d.expires_at, b.bottle_id, b.sender_id, b.sender_name, b.message, b.created_at, EXISTS( SELECT 1 FROM replies r WHERE r.delivery_id = d.delivery_id ) AS has_replied FROM deliveries d JOIN bottles b ON b.bottle_id = d.bottle_id WHERE d.recipient_id=? ORDER BY b.created_at DESC """, (user_id,), ).fetchall() sent_rows = self.conn.execute( """ SELECT bottle_id, sender_id, sender_name, message, created_at, expires_at, fanout FROM bottles WHERE sender_id=? ORDER BY created_at DESC """, (user_id,), ).fetchall() replies_rows = self.conn.execute( """ SELECT reply_id, bottle_id, recipient_id, replier_name, reply_text, created_at FROM replies WHERE sender_id=? ORDER BY created_at DESC """, (user_id,), ).fetchall() ``` ```python if parsed.path.startswith("/api/inbox/"): user_id = validate_user_id(parsed.path.rsplit("/", 1)[-1]) json_response(self, 200, self.db.inbox(user_id)) return ``` ### Technical Analysis The inbox endpoint treats a caller-provided `user_id` as sufficient proof of identity. It does not require an authenticated session, API credential, signed request, or ownership check. The response contains received messages, sent messages, replies, recipient identities, and `reply_token` values. These tokens are a ...[truncated 1244 chars]- Remediation
View remediation
