fix: prevent panic on invalid regex in reload annotation

ShouldReload compiled each comma-separated value of a named reload
annotation (e.g. secret.reloader.stakater.com/reload) with
regexp.MustCompile, which panics on an invalid pattern. The value comes
straight from a user-set annotation on a watched workload, and the queue
worker has no recover(), so a single malformed annotation (e.g.
"app-config[") on any workload in any watched namespace crashes Reloader
and stops reloads cluster-wide.

Use regexp.Compile and, on error, log and skip that pattern instead of
panicking.
This commit is contained in:
Nikolaus Schuetz
2026-07-22 00:51:47 -07:00
parent 20220ed7ef
commit 54e6b1c44f
2 changed files with 29 additions and 1 deletions
+5 -1
View File
@@ -276,7 +276,11 @@ func ShouldReload(config Config, resourceType string, annotations Map, podAnnota
values := strings.Split(annotationValue, ",")
for _, value := range values {
value = strings.TrimSpace(value)
re := regexp.MustCompile("^" + value + "$")
re, err := regexp.Compile("^" + value + "$")
if err != nil {
logrus.Errorf("Invalid regex %q in reload annotation %q on resource '%s' of type '%s'; skipping this pattern: %v", value, config.Annotation, config.ResourceName, config.Type, err)
continue
}
if re.Match([]byte(config.ResourceName)) {
return ReloadCheckResult{
ShouldReload: true,
+24
View File
@@ -222,3 +222,27 @@ func TestShouldReload_IssueRBACPermissionFixed(t *testing.T) {
})
}
}
// A malformed regex in a named reload annotation must not panic the operator.
// Regression test: previously regexp.MustCompile("^"+value+"$") panicked on an
// invalid pattern, crashing Reloader cluster-wide (no recover on the worker).
func TestShouldReload_InvalidRegexAnnotation_DoesNotPanic(t *testing.T) {
config := Config{
ResourceName: "app-config",
Annotation: "secret.reloader.stakater.com/reload",
}
annotations := Map{
// unbalanced bracket => invalid regex
"secret.reloader.stakater.com/reload": "app-config[",
}
opts := &ReloaderOptions{
ReloaderAutoAnnotation: "reloader.stakater.com/auto",
}
// Before the fix this panicked inside ShouldReload.
result := ShouldReload(config, "Deployment", annotations, Map{}, opts)
if result.ShouldReload {
t.Errorf("Expected ShouldReload=false for an invalid regex pattern, got=%v", result.ShouldReload)
}
}