From 8f2d1cb7f448a0574fee64f6b2027cc9440539b6 Mon Sep 17 00:00:00 2001 From: Saleh Date: Sat, 19 Sep 2026 02:56:04 +0300 Subject: [PATCH] plugin/cache: don't cache or panic on responses with no question (#8467) An upstream may return a NOERROR message with an empty question section (some plugins emit this during prefetch). response.Typify classifies it as NoError, so key falls through to m.Question[0] and panics, taking down the server. Skip caching such a malformed response and log a warning instead. Fixes #6051 Signed-off-by: Saleh --- plugin/cache/cache.go | 7 +++++++ plugin/cache/cache_test.go | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/plugin/cache/cache.go b/plugin/cache/cache.go index 8cb49dceb..149fc5803 100644 --- a/plugin/cache/cache.go +++ b/plugin/cache/cache.go @@ -91,6 +91,13 @@ func key(qname string, m *dns.Msg, t response.Type, do, cd bool) (bool, uint64) if m.Truncated { return false, 0 } + // A response with no question cannot be keyed or cached and would panic + // on m.Question[0] below. Some plugins can emit such a malformed message + // (e.g. during prefetch); warn and skip it rather than crash the server. + if len(m.Question) == 0 { + log.Warningf("Not caching malformed response with an empty question section for %q", qname) + return false, 0 + } // Nor errors or Meta or Update. if t == response.OtherError || t == response.Meta || t == response.Update { return false, 0 diff --git a/plugin/cache/cache_test.go b/plugin/cache/cache_test.go index 0fbaf390b..7065f1636 100644 --- a/plugin/cache/cache_test.go +++ b/plugin/cache/cache_test.go @@ -2008,3 +2008,16 @@ func TestCacheWriteMsgNilResponse(t *testing.T) { t.Error("Expected error when passing nil response to WriteMsg, got nil") } } + +func TestKeyEmptyQuestion(t *testing.T) { + // A response with an empty question section must be reported as + // non-cacheable instead of panicking on m.Question[0]. Some plugins can + // emit such a message (e.g. during prefetch). Regression test for #6051. + m := new(dns.Msg) + m.Response = true + m.Rcode = dns.RcodeSuccess + + if ok, _ := key("example.org.", m, response.NoError, false, false); ok { + t.Fatal("expected a response with an empty question section to be non-cacheable") + } +}