Found during the 2026-08 FerrVault operator audit.
Problem
The operator ships a ClusterRole granting secrets: get,list,watch,create,update,patch across every namespace (charts/ferrvault-operator/templates/clusterrole.yaml:25-27). That's inherent to a cluster-wide sync operator — but when --watch-namespace restricts the cache to one namespace (cmd/main.go:58-72), the RBAC is not correspondingly narrowed: the ServiceAccount can still read every Secret in the cluster, so a leaked operator token has cluster-wide blast radius even in single-namespace deployments.
(Pod security context is already good: runAsNonRoot, readOnlyRootFilesystem, dropped caps, uid 65532.)
Fix
When watchNamespace is set, render a namespaced Role + RoleBinding instead of the cluster-wide ClusterRole (chart conditional), so single-namespace installs get least privilege.
Found during the 2026-08 FerrVault operator audit.
Problem
The operator ships a ClusterRole granting
secrets: get,list,watch,create,update,patchacross every namespace (charts/ferrvault-operator/templates/clusterrole.yaml:25-27). That's inherent to a cluster-wide sync operator — but when--watch-namespacerestricts the cache to one namespace (cmd/main.go:58-72), the RBAC is not correspondingly narrowed: the ServiceAccount can still read every Secret in the cluster, so a leaked operator token has cluster-wide blast radius even in single-namespace deployments.(Pod security context is already good:
runAsNonRoot,readOnlyRootFilesystem, dropped caps, uid 65532.)Fix
When
watchNamespaceis set, render a namespacedRole+RoleBindinginstead of the cluster-wideClusterRole(chart conditional), so single-namespace installs get least privilege.