Skip to content

utilities: map checksum collision & IPv6 host parsing #1228

Description

@Jakob3xD

Summary

Two shared-utility bugs in internal/utilities/.

Findings

1. Map checksum concatenates values only — no keys, no separators → possible silent reconcile-skip (Medium)

internal/utilities/checksum.go:71-103

Both calculateMapStringString and calculateMapStringByte, after sorting keys, do:

for _, key := range keys {
    checksum += data[key]   // value only — no key, no separator
}

So {"a":"1","b":"23"}, {"a":"12","b":"3"} and {"a":"123"} all hash identically — key identity and value boundaries are both lost. The sibling CalculateStringSliceChecksum (:43-56) explicitly writes a {0} separator with the comment "Add separator to avoid collisions"; the map variants never got that fix.

CalculateMapChecksumSetObjectChecksum is the repo-wide change-detection mechanism (compared as GetObjectChecksum != CalculateMapChecksum(Data) across every cert/kubeconfig/kubeadm/datastore config Secret & ConfigMap). A collision means a genuine change hashes identical to the prior state and the reconciler skips an update it should apply — silent config/cert drift, no crash.

Note: for the actual data (PEM certificates, kubeconfigs, binary secrets) the probability of a real collision is negligible, so real-world impact is low. But the code is objectively missing key+separator that the sibling function already demonstrates as intended, and the fix is trivial.

Fix: feed keys, a separator and values into the hash, mirroring CalculateStringSliceChecksum:

h.Write([]byte(key)); h.Write([]byte{0}); h.Write(value); h.Write([]byte{0})

2. GetControlPlaneAddressAndPortFromHostname mis-parses IPv6 literals (Low)

internal/utilities/ingress.go:11-25

Splits on ":" and treats len(parts)==2 as host:port. IPv6 literals contain multiple colons (2001:db8::1, [2001:db8::1]:6443), so a raw IPv6 host yields len(parts)>2 and the port branch is skipped, while [addr]:port puts "[addr" (mangled brackets) into the address. Latent correctness bug for IPv6 clusters.

Fix: use net.SplitHostPort with a fallback for the no-port case instead of strings.Split(hostname, ":").


🤖 Reported as part of a Claude Code audit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions