From 398f29dced98bf8578957567239fbbe33cc013c3 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Mon, 10 Aug 2026 07:47:54 -0400 Subject: [PATCH] [voice_assistant] Reject external wake words without a usable model hash equals_hex needs exactly 64 hex characters, so an empty or truncated model_hash downloaded the whole model and then failed with a hash mismatch, which points at a corrupt download rather than a missing field. Skip the entry when it is cached instead. --- esphome/components/voice_assistant/voice_assistant.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 7181b65181..6052d64190 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -1235,6 +1235,8 @@ constexpr size_t MODEL_DOWNLOAD_CHUNK_SIZE = 1024; // Sanity bounds for the model parameters declared in the manifest. constexpr size_t MAX_SLIDING_WINDOW_SIZE = 50; constexpr size_t MAX_TENSOR_ARENA_SIZE = 1024 * 1024; +// A hex-encoded SHA256 is always 64 characters. Anything else cannot be parsed for comparison. +constexpr size_t SHA256_HEX_LENGTH = 64; // Verifies a buffer against an expected hex-encoded SHA256. A free function (not a method) so it can never // read VoiceAssistant state, and so the hasher stays within a single stack frame as the hardware-accelerated @@ -1263,6 +1265,14 @@ void VoiceAssistant::cache_external_wake_words_(const std::vector(ww.id.size()), ww.id.c_str()); + continue; + } // Copy every StringRef into an owning string; the proto StringRefs point into the receive buffer and // dangle once this handler returns. CachedExternalWakeWord entry;