T09 · Insecure Skill Coding Practices
- Location
hermes.py:43- Finding
Premature Recycling of Mutable Messages Causes Cross-Delivery Data Corruption
- Content
View full analysis
int: with self.lock: subscribers = dict(self.subscribers) if msg.from_agent in subscribers: del subscribers[msg.from_agent] count = len(subscribers) for agent_id, handler in subscribers.items(): executor.submit(handler, msg) return count ``` ```python msg = self._acquire_message(topic, from_agent, session_id, payload, trace_id) delivered = synapse.deliver(msg, self._executor) with self._global_lock: self._stats["total_delivered"] += delivered self._executor.submit(self._safe_release, msg) return delivered ``` ### Technical Analysis The router passes the same mutable `HermesMessage` instance to every asynchronous subscriber handler. Immediately after queuing the handlers, it queues `_safe_release`, which returns that message to the reusable object pool. Although the release task is submitted after the handler tasks, `ThreadPoolExecutor` does not guarantee that all previously submitted handlers have completed before another worker executes the release task. For example, one subscriber may block while another worker reaches `_safe_release`. Once the message is returned to the pool, a later call to `_acquire_message` can obtain and overwrite the object’s `topic`, `from_agent`, `session_id`, `payload`, `trace_id`, and `sent_at` fields while the earlier subscriber still holds a reference to it. This creates a time-of-check/time-of-use race over shared mutable state. A subscriber authorized to receive one publication may observe fields or payload data belonging to a different publication. ### Attack Path 1. An attacker controls or influences a subscribed message handler. 2. The handler deliberately blocks or delays before re ...[truncated 1303 chars]- Remediation
View remediation
