Bound wakeword payload length to prevent DoS

Added a 10MB limit and lower bound to `payload_length` read from network payloads in `wakeword.py` and `wakeword_bench.py` to prevent unbounded memory allocation and infinite waiting for malicious/corrupt frames.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
mARTin-B78 2026-06-10 19:40:25 +00:00
parent 8f056e8cf0
commit 16f155ff7b
3 changed files with 12 additions and 0 deletions

3
.jules/sentinel.md Normal file
View File

@ -0,0 +1,3 @@
## 2025-02-14 — Bound wakeword payload length
**Learning:** `payload_length` read from network JSON payloads in `wakeword.py` and `wakeword_bench.py` lacked bounds checks, allowing a malicious Wyoming server (or MITM) to cause a DoS by providing a huge length and freezing the read loop or consuming all memory.
**Action:** Added `if not (0 <= payload_len <= 10 * 1024 * 1024):` bounds check to safely drop oversized or negative `payload_length` frames.

View File

@ -112,6 +112,9 @@ class WakewordListener:
self._handle_detection()
payload_len = msg.get("payload_length", 0)
if not (0 <= payload_len <= 10 * 1024 * 1024):
logbuffer.log(f"[wakeword] Disconnecting: payload length {payload_len} out of bounds", level="WARNING")
break
if payload_len > 0:
# Consume payload
remaining = payload_len
@ -258,6 +261,9 @@ class WakewordActionListener:
self._stop_event.set() # one-shot: stop after first fire
cb()
payload_len = msg.get("payload_length", 0)
if not (0 <= payload_len <= 10 * 1024 * 1024):
logbuffer.log(f"[wakeword-action] Disconnecting: payload length {payload_len} out of bounds", level="WARNING")
break
if payload_len > 0:
remaining = payload_len
while remaining > 0:

View File

@ -322,6 +322,9 @@ def _drain_detections(buf: bytes) -> tuple[bytes, int]:
except (ValueError, UnicodeDecodeError):
return rest, found
plen = msg.get("payload_length", 0) or 0
if not (0 <= plen <= 10 * 1024 * 1024):
# Abort this buffer completely if framing is corrupt or size is unreasonable
return b"", found
if len(rest) < plen:
return buf, found # payload not fully arrived yet; wait for more
rest = rest[plen:]