Skip to content

fix(operator): ensureTargetSecret writes StringData so CreateOrUpdate issues an Update every reconcile #212

Description

@BryanFRD

Found during the 2026-08 FerrVault operator audit.

Problem

internal/controller/ferrvaultsecret_sync.go:49-67 — the CreateOrUpdate mutate sets secret.StringData = data; secret.Data = nil. The API server never returns StringData (it's write-only, folded into Data), so the live object always has Data != nil, StringData == nil while the mutated object has the reverse. equality.Semantic.DeepEqual therefore never matches and CreateOrUpdate issues an Update on every reconcile even when content is unchanged.

Because the controller Owns(&corev1.Secret{}) (ferrvaultsecret_controller.go:210), each self-write re-enqueues the owner — a second independent driver of the hot loop (see the GenerationChangedPredicate issue), plus constant resourceVersion churn on every managed Secret.

Fix

Write secret.Data (raw []byte) instead of StringData so the round-tripped object is byte-stable and CreateOrUpdate becomes a no-op when nothing changed. Alternatively short-circuit when the stored content-hash annotation already equals the new hash.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High prioritybugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions