Skip to content

Security: QuestionHistory grows unbounded between 10s cleanup ticks under a question flood #1723

@bluetoothbot

Description

@bluetoothbot

Problem

QueryHandler.async_response calls self.question_history.add_question_at_time(question, now, known_answers_set) for every non-unicast question in every incoming query the registry can match. QuestionHistory._history is a plain dict[DNSQuestion, (time, known_answers)] with no size cap; the only eviction is async_expire, called from the engine's periodic cleanup at _CACHE_CLEANUP_INTERVAL = 10 seconds. A LAN peer that streams queries with synthetic-but-matching service names — each carrying many distinct questions — can grow _history (and the retained known_answers sets) for up to ~10 s before the next cleanup tick fires, easily reaching hundreds of MB at line-rate.

Why This Matters

Same threat model and same daemon (Home Assistant / IoT bridge) as the _deferred issue; this is a second independent vector that lets a malicious LAN device drive the process toward OOM. The 10 s cleanup interval is long enough for the burst to land before the periodic sweep runs, and add_question_at_time does not consult the size of the dict it's growing.

Suggested Fix

Add a hard cap on _history (e.g. a few thousand entries) and refuse to insert (or evict the oldest by insertion order — dict is ordered) when at cap. Optionally trigger an opportunistic async_expire(now) from inside add_question_at_time when len(self._history) crosses a high-water mark, instead of waiting for the 10 s cleanup timer. Track known_answers as a count or hashed digest if the full set is not needed for the suppression decision.

Details

Severity 🟡 Medium
Category dos
Location src/zeroconf/_history.py:34-77, src/zeroconf/_handlers/query_handler.py:354-356, src/zeroconf/_engine.py:129-144
Effort ⚡ Quick fix

🤖 Created by Kōan from audit session

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions