From 6676e6185d1d750d2bca8f163710feed469610c3 Mon Sep 17 00:00:00 2001 From: Ville Vesilehto Date: Mon, 6 Oct 2025 10:06:28 +0300 Subject: [PATCH] =?UTF-8?q?fix(sign):=20reject=20invalid=20UTF=E2=80=918?= =?UTF-8?q?=20dbfile=20token=20(#7589)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The coredns/caddy lexer replaces invalid UTF‑8 bytes in tokens with U+FFFD. When that lossy-decoded value is used as `dbfile` in the sign plugin, the source zone file path never exists. On startup/refresh, the `resign()` function sees the signed file missing and triggers signing. Consequently `Sign()` then fails opening the bogus path, the signed file is never created, and the cycle repeats across all expanded origins (e.g., reverse CIDRs), causing unbounded churn/OOM. Validate `dbfile` in setup and error if it contains U+FFFD. Add a regression test. Note: Unicode paths are supported; only U+FFFD (replacement-rune) is rejected. Signed-off-by: Ville Vesilehto --- plugin/sign/setup.go | 6 ++++++ plugin/sign/setup_test.go | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/plugin/sign/setup.go b/plugin/sign/setup.go index e5f5295a0..ed3e6bda0 100644 --- a/plugin/sign/setup.go +++ b/plugin/sign/setup.go @@ -4,6 +4,7 @@ import ( "fmt" "math/rand" "path/filepath" + "strings" "time" "github.com/coredns/caddy" @@ -50,6 +51,11 @@ func parse(c *caddy.Controller) (*Sign, error) { dbfile = filepath.Join(config.Root, dbfile) } + // Validate dbfile token to avoid infinite signing loops caused by invalid paths + if strings.ContainsRune(dbfile, '\uFFFD') { + return nil, fmt.Errorf("dbfile %q contains invalid characters", dbfile) + } + origins := plugin.OriginsFromArgsOrServerBlock(c.RemainingArgs(), c.ServerBlockKeys) signers := make([]*Signer, len(origins)) for i := range origins { diff --git a/plugin/sign/setup_test.go b/plugin/sign/setup_test.go index 93d779a26..cb4a6f522 100644 --- a/plugin/sign/setup_test.go +++ b/plugin/sign/setup_test.go @@ -73,3 +73,14 @@ func TestParse(t *testing.T) { } } } + +// With setup validation in place, an invalid utf-8 dbfile token must cause parse() to error. +func TestParseRejectsInvalidDbfileToken(t *testing.T) { + input := "sign \"\xff\" 8.44.in-addr.arpa. 9.44.in-addr.arpa. {}" + c := caddy.NewTestController("dns", input) + + _, err := parse(c) + if err == nil { + t.Fatalf("expected parse to fail for invalid dbfile token") + } +}